| #!/usr/bin/python | |
| # -*- python -*- | |
| # | |
| # Keycode Map Generator | |
| # | |
| # Copyright (C) 2009-2017 Red Hat, Inc. | |
| # | |
| # This file is dual license under the terms of the GPLv2 or later | |
| # and 3-clause BSD licenses. | |
| # | |
| # Requires >= 2.6 | |
| from __future__ import print_function | |
| import csv | |
| import argparse | |
| import hashlib | |
| import time | |
| import sys | |
| class Database: | |
| # Linux: linux/input.h | |
| MAP_LINUX = "linux" | |
| # OS-X: Carbon/HIToolbox/Events.h | |
| MAP_OSX = "osx" | |
| # AT Set 1: linux/drivers/input/keyboard/atkbd.c | |
| # (atkbd_set2_keycode + atkbd_unxlate_table) | |
| MAP_ATSET1 = "atset1" | |
| # AT Set 2: linux/drivers/input/keyboard/atkbd.c | |
| # (atkbd_set2_keycode) | |
| MAP_ATSET2 = "atset2" | |
| # AT Set 3: linux/drivers/input/keyboard/atkbd.c | |
| # (atkbd_set3_keycode) | |
| MAP_ATSET3 = "atset3" | |
| # Linux RAW: linux/drivers/char/keyboard.c (x86_keycodes) | |
| MAP_XTKBD = "xtkbd" | |
| # USB HID: linux/drivers/hid/usbhid/usbkbd.c (usb_kbd_keycode) | |
| MAP_USB = "usb" | |
| # Win32: mingw32/winuser.h | |
| MAP_WIN32 = "win32" | |
| # XWin XT: xorg-server/hw/xwin/{winkeybd.c,winkeynames.h} | |
| # (xt + manually transcribed) | |
| MAP_XWINXT = "xwinxt" | |
| # X11: http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h | |
| MAP_X11 = "x11" | |
| # XKBD XT: xf86-input-keyboard/src/at_scancode.c | |
| # (xt + manually transcribed) | |
| MAP_XKBDXT = "xkbdxt" | |
| # Xorg with evdev: linux + an offset | |
| MAP_XORGEVDEV = "xorgevdev" | |
| # Xorg with kbd: xkbdxt + an offset | |
| MAP_XORGKBD = "xorgkbd" | |
| # Xorg with OS-X: osx + an offset | |
| MAP_XORGXQUARTZ = "xorgxquartz" | |
| # Xorg + Cygwin: xwinxt + an offset | |
| MAP_XORGXWIN = "xorgxwin" | |
| # XT over RFB: xtkbd + special re-encoding of high bit | |
| MAP_RFB = "rfb" | |
| # HTML codes | |
| MAP_HTML = "html" | |
| # XKB key names | |
| MAP_XKB = "xkb" | |
| MAP_LIST = ( | |
| MAP_LINUX, | |
| MAP_OSX, | |
| MAP_ATSET1, | |
| MAP_ATSET2, | |
| MAP_ATSET3, | |
| MAP_USB, | |
| MAP_WIN32, | |
| MAP_XWINXT, | |
| MAP_XKBDXT, | |
| MAP_X11, | |
| # These are derived from maps above | |
| MAP_XTKBD, | |
| MAP_XORGEVDEV, | |
| MAP_XORGKBD, | |
| MAP_XORGXQUARTZ, | |
| MAP_XORGXWIN, | |
| MAP_RFB, | |
| ) | |
| CODE_COLUMNS = { | |
| MAP_LINUX: 1, | |
| MAP_OSX: 3, | |
| MAP_ATSET1: 4, | |
| MAP_ATSET2: 5, | |
| MAP_ATSET3: 6, | |
| MAP_USB: 7, | |
| MAP_WIN32: 9, | |
| MAP_XWINXT: 10, | |
| MAP_XKBDXT: 11, | |
| MAP_X11: 13, | |
| } | |
| NAME_COLUMNS = { | |
| MAP_LINUX: 0, | |
| MAP_OSX: 2, | |
| MAP_WIN32: 8, | |
| MAP_X11: 12, | |
| MAP_HTML: 14, | |
| MAP_XKB: 15, | |
| } | |
| def __init__(self): | |
| self.mapto = {} | |
| self.mapfrom = {} | |
| self.mapname = {} | |
| self.mapchecksum = None | |
| for name in self.MAP_LIST: | |
| # Key is a MAP_LINUX, value is a MAP_XXX | |
| self.mapto[name] = {} | |
| # key is a MAP_XXX, value is a MAP_LINUX | |
| self.mapfrom[name] = {} | |
| for name in self.NAME_COLUMNS.keys(): | |
| # key is a MAP_LINUX, value is a string | |
| self.mapname[name] = {} | |
| def _generate_checksum(self, filename): | |
| hash = hashlib.sha256() | |
| with open(filename, "rb") as f: | |
| for chunk in iter(lambda: f.read(4096), b""): | |
| hash.update(chunk) | |
| self.mapchecksum = hash.hexdigest() | |
| def load(self, filename): | |
| self._generate_checksum(filename) | |
| with open(filename, 'r') as f: | |
| reader = csv.reader(f) | |
| first = True | |
| for row in reader: | |
| # Discard column headings | |
| if first: | |
| first = False | |
| continue | |
| # We special case MAP_LINUX since that is out | |
| # master via which all other mappings are done | |
| linux = self.load_linux(row) | |
| # Now load all the remaining master data values | |
| self.load_data(row, linux) | |
| # Then load all the keycode names | |
| self.load_names(row, linux) | |
| # Finally calculate derived key maps | |
| self.derive_data(row, linux) | |
| def load_linux(self, row): | |
| col = self.CODE_COLUMNS[self.MAP_LINUX] | |
| linux = row[col] | |
| if linux.startswith("0x"): | |
| linux = int(linux, 16) | |
| else: | |
| linux = int(linux, 10) | |
| self.mapto[self.MAP_LINUX][linux] = linux | |
| self.mapfrom[self.MAP_LINUX][linux] = linux | |
| return linux | |
| def load_data(self, row, linux): | |
| for mapname in self.CODE_COLUMNS: | |
| if mapname == self.MAP_LINUX: | |
| continue | |
| col = self.CODE_COLUMNS[mapname] | |
| val = row[col] | |
| if val == "": | |
| continue | |
| if val.startswith("0x"): | |
| val = int(val, 16) | |
| else: | |
| val = int(val, 10) | |
| self.mapto[mapname][linux] = val | |
| self.mapfrom[mapname][val] = linux | |
| def load_names(self, row, linux): | |
| for mapname in self.NAME_COLUMNS: | |
| col = self.NAME_COLUMNS[mapname] | |
| val = row[col] | |
| if val == "": | |
| continue | |
| self.mapname[mapname][linux] = val | |
| def derive_data(self, row, linux): | |
| # Linux RAW is XT scan codes with special encoding of the | |
| # 0xe0 scan codes | |
| if linux in self.mapto[self.MAP_ATSET1]: | |
| at1 = self.mapto[self.MAP_ATSET1][linux] | |
| if at1 > 0x7f: | |
| assert((at1 & ~0x7f) == 0xe000) | |
| xtkbd = 0x100 | (at1 & 0x7f) | |
| else: | |
| xtkbd = at1 | |
| self.mapto[self.MAP_XTKBD][linux] = xtkbd | |
| self.mapfrom[self.MAP_XTKBD][xtkbd] = linux | |
| # Xorg KBD is XKBD XT offset by 8 | |
| if linux in self.mapto[self.MAP_XKBDXT]: | |
| xorgkbd = self.mapto[self.MAP_XKBDXT][linux] + 8 | |
| self.mapto[self.MAP_XORGKBD][linux] = xorgkbd | |
| self.mapfrom[self.MAP_XORGKBD][xorgkbd] = linux | |
| # Xorg evdev is Linux offset by 8 | |
| self.mapto[self.MAP_XORGEVDEV][linux] = linux + 8 | |
| self.mapfrom[self.MAP_XORGEVDEV][linux + 8] = linux | |
| # Xorg XQuartx is OS-X offset by 8 | |
| if linux in self.mapto[self.MAP_OSX]: | |
| xorgxquartz = self.mapto[self.MAP_OSX][linux] + 8 | |
| self.mapto[self.MAP_XORGXQUARTZ][linux] = xorgxquartz | |
| self.mapfrom[self.MAP_XORGXQUARTZ][xorgxquartz] = linux | |
| # Xorg Xwin (aka Cygwin) is XWin XT offset by 8 | |
| if linux in self.mapto[self.MAP_XWINXT]: | |
| xorgxwin = self.mapto[self.MAP_XWINXT][linux] + 8 | |
| self.mapto[self.MAP_XORGXWIN][linux] = xorgxwin | |
| self.mapfrom[self.MAP_XORGXWIN][xorgxwin] = linux | |
| # RFB keycodes are XT scan codes with a slightly | |
| # different encoding of 0xe0 scan codes | |
| if linux in self.mapto[self.MAP_ATSET1]: | |
| at1 = self.mapto[self.MAP_ATSET1][linux] | |
| if at1 > 0x7f: | |
| assert((at1 & ~0x7f) == 0xe000) | |
| rfb = 0x80 | (at1 & 0x7f) | |
| else: | |
| rfb = at1 | |
| self.mapto[self.MAP_RFB][linux] = rfb | |
| self.mapfrom[self.MAP_RFB][rfb] = linux | |
| class LanguageGenerator(object): | |
| def _boilerplate(self, lines): | |
| raise NotImplementedError() | |
| def generate_header(self, database, args): | |
| today = time.strftime("%Y-%m-%d %H:%M") | |
| self._boilerplate([ | |
| "This file is auto-generated from keymaps.csv on %s" % today, | |
| "Database checksum sha256(%s)" % database.mapchecksum, | |
| "To re-generate, run:", | |
| " %s" % args, | |
| ]) | |
| class LanguageSrcGenerator(LanguageGenerator): | |
| def _array_start_code(self, varname, length): | |
| raise NotImplementedError() | |
| def _array_start_name(self, varname, length): | |
| raise NotImplementedError() | |
| def _array_end(self): | |
| raise NotImplementedError() | |
| def _array_entry_code(self, index, value, comment): | |
| raise NotImplementedError() | |
| def _array_entry_name(self, index, value, comment): | |
| raise NotImplementedError() | |
| def generate_code_map(self, varname, database, frommapname, tomapname): | |
| if frommapname not in database.mapfrom: | |
| raise Exception("Unknown map %s, expected one of %s" % ( | |
| frommapname, ", ".join(database.mapfrom.keys()))) | |
| if tomapname not in database.mapto: | |
| raise Exception("Unknown map %s, expected one of %s" % ( | |
| tomapname, ", ".join(database.mapto.keys()))) | |
| tolinux = database.mapfrom[frommapname] | |
| fromlinux = database.mapto[tomapname] | |
| if varname is None: | |
| varname = "code_map_%s_to_%s" % (frommapname, tomapname) | |
| frommax = 0 | |
| for key in tolinux.keys(): | |
| if key > frommax: | |
| frommax = key | |
| self._array_start_code(varname, frommax + 1) | |
| for src in range(frommax + 1): | |
| linux = tolinux.get(src, None) | |
| if linux is None: | |
| dst = None | |
| else: | |
| dst = fromlinux.get(linux, None) | |
| comment = "%s -> %s -> %s" % (self._label(database, frommapname, src, linux), | |
| self._label(database, Database.MAP_LINUX, linux, linux), | |
| self._label(database, tomapname, dst, linux)) | |
| self._array_entry_code(src, dst, comment) | |
| self._array_end() | |
| def generate_code_table(self, varname, database, mapname): | |
| if mapname not in database.mapto: | |
| raise Exception("Unknown map %s, expected one of %s" % ( | |
| mapname, ", ".join(database.mapto.keys()))) | |
| keys = database.mapto[Database.MAP_LINUX].keys() | |
| keys.sort() | |
| names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] | |
| if varname is None: | |
| varname = "code_table_%s" % mapname | |
| self._array_start_code(varname, len(keys)) | |
| for i in range(len(keys)): | |
| key = keys[i] | |
| dst = database.mapto[mapname].get(key, None) | |
| self._array_entry_code(i, dst, names[i]) | |
| self._array_end() | |
| def generate_name_map(self, varname, database, frommapname, tomapname): | |
| if frommapname not in database.mapfrom: | |
| raise Exception("Unknown map %s, expected one of %s" % ( | |
| frommapname, ", ".join(database.mapfrom.keys()))) | |
| if tomapname not in database.mapname: | |
| raise Exception("Unknown map %s, expected one of %s" % ( | |
| tomapname, ", ".join(database.mapname.keys()))) | |
| tolinux = database.mapfrom[frommapname] | |
| fromlinux = database.mapname[tomapname] | |
| if varname is None: | |
| varname = "name_map_%s_to_%s" % (frommapname, tomapname) | |
| frommax = 0 | |
| for key in tolinux.keys(): | |
| if key > frommax: | |
| frommax = key | |
| self._array_start_name(varname, frommax + 1) | |
| for src in range(frommax + 1): | |
| linux = tolinux.get(src, None) | |
| if linux is None: | |
| dst = None | |
| else: | |
| dst = fromlinux.get(linux, None) | |
| comment = "%s -> %s -> %s" % (self._label(database, frommapname, src, linux), | |
| self._label(database, Database.MAP_LINUX, linux, linux), | |
| self._label(database, tomapname, dst, linux)) | |
| self._array_entry_name(src, dst, comment) | |
| self._array_end() | |
| def generate_name_table(self, varname, database, mapname): | |
| if mapname not in database.mapname: | |
| raise Exception("Unknown map %s, expected one of %s" % ( | |
| mapname, ", ".join(database.mapname.keys()))) | |
| keys = database.mapto[Database.MAP_LINUX].keys() | |
| keys.sort() | |
| names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] | |
| if varname is None: | |
| varname = "name_table_%s" % mapname | |
| self._array_start_name(varname, len(keys)) | |
| for i in range(len(keys)): | |
| key = keys[i] | |
| dst = database.mapname[mapname].get(key, None) | |
| self._array_entry_name(i, dst, names[i]) | |
| self._array_end() | |
| def _label(self, database, mapname, val, linux): | |
| if mapname in database.mapname: | |
| return "%s:%s (%s)" % (mapname, val, database.mapname[mapname].get(linux, "unnamed")) | |
| else: | |
| return "%s:%s" % (mapname, val) | |
| class LanguageDocGenerator(LanguageGenerator): | |
| def _array_start_name_doc(self, varname, namemap): | |
| raise NotImplementedError() | |
| def _array_start_code_doc(self, varname, namemap, codemap): | |
| raise NotImplementedError() | |
| def _array_end(self): | |
| raise NotImplementedError() | |
| def _array_name_entry(self, value, name): | |
| raise NotImplementedError() | |
| def _array_code_entry(self, value, name): | |
| raise NotImplementedError() | |
| def generate_name_docs(self, varname, database, mapname): | |
| if mapname not in database.mapname: | |
| raise Exception("Unknown map %s, expected one of %s" % ( | |
| mapname, ", ".join(database.mapname.keys()))) | |
| keys = database.mapto[Database.MAP_LINUX].keys() | |
| keys.sort() | |
| names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] | |
| if varname is None: | |
| varname = mapname | |
| self._array_start_name_doc(varname, mapname) | |
| for i in range(len(keys)): | |
| key = keys[i] | |
| dst = database.mapname[mapname].get(key, None) | |
| self._array_name_entry(key, dst) | |
| self._array_end() | |
| def generate_code_docs(self, varname, database, mapname): | |
| if mapname not in database.mapfrom: | |
| raise Exception("Unknown map %s, expected one of %s" % ( | |
| mapname, ", ".join(database.mapfrom.keys()))) | |
| tolinux = database.mapfrom[mapname] | |
| keys = tolinux.keys() | |
| keys.sort() | |
| if mapname in database.mapname: | |
| names = database.mapname[mapname] | |
| namemap = mapname | |
| else: | |
| names = database.mapname[Database.MAP_LINUX] | |
| namemap = Database.MAP_LINUX | |
| if varname is None: | |
| varname = mapname | |
| self._array_start_code_doc(varname, mapname, namemap) | |
| for i in range(len(keys)): | |
| key = keys[i] | |
| self._array_code_entry(key, names.get(tolinux[key], "unnamed")) | |
| self._array_end() | |
| class CLanguageGenerator(LanguageSrcGenerator): | |
| def __init__(self, inttypename, strtypename): | |
| self.inttypename = inttypename | |
| self.strtypename = strtypename | |
| def _boilerplate(self, lines): | |
| print("/*") | |
| for line in lines: | |
| print(" * %s" % line) | |
| print("*/") | |
| def _array_start_code(self, varname, length): | |
| print("const %s %s[%d] = {" % (self.inttypename, varname, length)) | |
| def _array_start_name(self, varname, length): | |
| print("const %s %s[%d] = {" % (self.strtypename, varname, length)) | |
| def _array_end(self): | |
| print("};") | |
| def _array_entry_code(self, index, value, comment): | |
| if value is not None: | |
| print(" [0x%x] = 0x%x, /* %s */" % (index, value, comment)) | |
| def _array_entry_name(self, index, value, comment): | |
| if value is not None: | |
| print(" [0x%x] = \"%s\", /* %s */" % (index, value, comment)) | |
| class CppLanguageGenerator(CLanguageGenerator): | |
| # designated initializers not available in C++ | |
| def _array_entry_code(self, index, value, comment): | |
| if value is not None: | |
| print(" 0x%x, /* %s */" % (value, comment)) | |
| else: | |
| print(" 0, /* %s */" % comment) | |
| def _array_entry_name(self, index, value, comment): | |
| if value is not None: | |
| print(" \"%s\", /* %s */" % (value, comment)) | |
| else: | |
| print(" 0, /* %s */" % comment) | |
| class StdCLanguageGenerator(CLanguageGenerator): | |
| def __init__(self): | |
| super(StdCLanguageGenerator, self).__init__("unsigned short", "char *") | |
| class StdCppLanguageGenerator(CppLanguageGenerator): | |
| def __init__(self): | |
| super(StdCppLanguageGenerator, self).__init__("unsigned short", "char *") | |
| class GLib2LanguageGenerator(CLanguageGenerator): | |
| def __init__(self): | |
| super(GLib2LanguageGenerator, self).__init__("guint16", "gchar *") | |
| class PythonLanguageGenerator(LanguageSrcGenerator): | |
| def _boilerplate(self, lines): | |
| print("#") | |
| for line in lines: | |
| print("# %s" % line) | |
| print("#") | |
| def _array_start_code(self, varname, length): | |
| print("%s = [" % varname) | |
| def _array_start_name(self, varname, length): | |
| print("%s = [" % varname) | |
| def _array_end(self): | |
| print("]") | |
| def _array_entry_code(self, index, value, comment): | |
| if value is None: | |
| print(" None, # %s" % (comment)) | |
| else: | |
| print(" 0x%x, # %s" % (value, comment)) | |
| def _array_entry_name(self, index, value, comment): | |
| if value is None: | |
| print(" None, # %s" % (comment)) | |
| else: | |
| print(" \"%s\", # %s" % (value, comment)) | |
| class PerlLanguageGenerator(LanguageSrcGenerator): | |
| def _boilerplate(self, lines): | |
| print("#") | |
| for line in lines: | |
| print("# %s" % line) | |
| print("#") | |
| def _array_start_code(self, varname, length): | |
| print("my @%s = (" % varname) | |
| def _array_start_name(self, varname, length): | |
| print("my @%s = (" % varname) | |
| def _array_end(self): | |
| print(");") | |
| def _array_entry_code(self, index, value, comment): | |
| if value is None: | |
| print(" undef, # %s" % (comment)) | |
| else: | |
| print(" 0x%x, # %s" % (value, comment)) | |
| def _array_entry_name(self, index, value, comment): | |
| if value is None: | |
| print(" undef, # %s" % (comment)) | |
| else: | |
| print(" \"%s\", # %s" % (value, comment)) | |
| class PodLanguageGenerator(LanguageDocGenerator): | |
| def _boilerplate(self, lines): | |
| print("#") | |
| for line in lines: | |
| print("# %s" % line) | |
| print("#") | |
| def _array_start_name_doc(self, varname, namemap): | |
| print("=head1 %s" % varname) | |
| print("") | |
| print("List of %s key code names, with corresponding key code values" % namemap) | |
| print("") | |
| print("=over 4") | |
| print("") | |
| def _array_start_code_doc(self, varname, codemap, namemap): | |
| print("=head1 %s" % varname) | |
| print("") | |
| print("List of %s key code values, with corresponding %s key code names" % (codemap, namemap)) | |
| print("") | |
| print("=over 4") | |
| print("") | |
| def _array_end(self): | |
| print("=back") | |
| print("") | |
| def _array_name_entry(self, value, name): | |
| print("=item %s" % name) | |
| print("") | |
| print("Key value %d (0x%x)" % (value, value)) | |
| print("") | |
| def _array_code_entry(self, value, name): | |
| print("=item %d (0x%x)" % (value, value)) | |
| print("") | |
| print("Key name %s" % name) | |
| print("") | |
| SRC_GENERATORS = { | |
| "stdc": StdCLanguageGenerator(), | |
| "stdc++": StdCppLanguageGenerator(), | |
| "glib2": GLib2LanguageGenerator(), | |
| "python2": PythonLanguageGenerator(), | |
| "python3": PythonLanguageGenerator(), | |
| "perl": PerlLanguageGenerator(), | |
| } | |
| DOC_GENERATORS = { | |
| "pod": PodLanguageGenerator(), | |
| } | |
| def code_map(args): | |
| database = Database() | |
| database.load(args.keymaps) | |
| cliargs = ["keymap-gen", "--lang=%s" % args.lang] | |
| if args.varname is not None: | |
| cliargs.append("--varname=%s" % args.varname) | |
| cliargs.extend(["code-map", "keymaps.csv", args.frommapname, args.tomapname]) | |
| SRC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) | |
| SRC_GENERATORS[args.lang].generate_code_map(args.varname, database, args.frommapname, args.tomapname) | |
| def code_table(args): | |
| database = Database() | |
| database.load(args.keymaps) | |
| cliargs = ["keymap-gen", "--lang=%s" % args.lang] | |
| if args.varname is not None: | |
| cliargs.append("--varname=%s" % args.varname) | |
| cliargs.extend(["code-table", "keymaps.csv", args.mapname]) | |
| SRC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) | |
| SRC_GENERATORS[args.lang].generate_code_table(args.varname, database, args.mapname) | |
| def name_map(args): | |
| database = Database() | |
| database.load(args.keymaps) | |
| cliargs = ["keymap-gen", "--lang=%s" % args.lang] | |
| if args.varname is not None: | |
| cliargs.append("--varname=%s" % args.varname) | |
| cliargs.extend(["name-map", "keymaps.csv", args.frommapname, args.tomapname]) | |
| SRC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) | |
| SRC_GENERATORS[args.lang].generate_name_map(args.varname, database, args.frommapname, args.tomapname) | |
| def name_table(args): | |
| database = Database() | |
| database.load(args.keymaps) | |
| cliargs = ["keymap-gen", "--lang=%s" % args.lang] | |
| if args.varname is not None: | |
| cliargs.append("--varname=%s" % args.varname) | |
| cliargs.extend(["name-table", "keymaps.csv", args.mapname]) | |
| SRC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) | |
| SRC_GENERATORS[args.lang].generate_name_table(args.varname, database, args.mapname) | |
| def code_docs(args): | |
| database = Database() | |
| database.load(args.keymaps) | |
| cliargs = ["keymap-gen", "--lang=%s" % args.lang] | |
| if args.varname is not None: | |
| cliargs.append("--varname=%s" % args.varname) | |
| cliargs.extend(["code-docs", "keymaps.csv", args.mapname]) | |
| DOC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) | |
| DOC_GENERATORS[args.lang].generate_code_docs(args.varname, database, args.mapname) | |
| def name_docs(args): | |
| database = Database() | |
| database.load(args.keymaps) | |
| cliargs = ["keymap-gen", "--lang=%s" % args.lang] | |
| if args.varname is not None: | |
| cliargs.append("--varname=%s" % args.varname) | |
| cliargs.extend(["name-docs", "keymaps.csv", args.mapname]) | |
| DOC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs)) | |
| DOC_GENERATORS[args.lang].generate_name_docs(args.varname, database, args.mapname) | |
| def usage(): | |
| print ("Please select a command:") | |
| print (" 'code-map', 'code-table', 'name-map', 'name-table', 'docs'") | |
| sys.exit(1) | |
| def main(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--lang", default="stdc", | |
| help="Output language, (src=%s, doc=%s)" % ( | |
| ",".join(SRC_GENERATORS.keys()), | |
| ",".join(DOC_GENERATORS.keys()))) | |
| parser.add_argument("--varname", default=None, | |
| help="Data variable name") | |
| subparsers = parser.add_subparsers(help="sub-command help") | |
| codemapparser = subparsers.add_parser("code-map", help="Generate a mapping between code tables") | |
| codemapparser.add_argument("keymaps", help="Path to keymap CSV data file") | |
| codemapparser.add_argument("frommapname", help="Source code table name") | |
| codemapparser.add_argument("tomapname", help="Target code table name") | |
| codemapparser.set_defaults(func=code_map) | |
| codetableparser = subparsers.add_parser("code-table", help="Generate a flat code table") | |
| codetableparser.add_argument("keymaps", help="Path to keymap CSV data file") | |
| codetableparser.add_argument("mapname", help="Code table name") | |
| codetableparser.set_defaults(func=code_table) | |
| namemapparser = subparsers.add_parser("name-map", help="Generate a mapping to names") | |
| namemapparser.add_argument("keymaps", help="Path to keymap CSV data file") | |
| namemapparser.add_argument("frommapname", help="Source code table name") | |
| namemapparser.add_argument("tomapname", help="Target name table name") | |
| namemapparser.set_defaults(func=name_map) | |
| nametableparser = subparsers.add_parser("name-table", help="Generate a flat name table") | |
| nametableparser.add_argument("keymaps", help="Path to keymap CSV data file") | |
| nametableparser.add_argument("mapname", help="Name table name") | |
| nametableparser.set_defaults(func=name_table) | |
| codedocsparser = subparsers.add_parser("code-docs", help="Generate code documentation") | |
| codedocsparser.add_argument("keymaps", help="Path to keymap CSV data file") | |
| codedocsparser.add_argument("mapname", help="Code table name") | |
| codedocsparser.set_defaults(func=code_docs) | |
| namedocsparser = subparsers.add_parser("name-docs", help="Generate name documentation") | |
| namedocsparser.add_argument("keymaps", help="Path to keymap CSV data file") | |
| namedocsparser.add_argument("mapname", help="Name table name") | |
| namedocsparser.set_defaults(func=name_docs) | |
| args = parser.parse_args() | |
| if hasattr(args, "func"): | |
| args.func(args) | |
| else: | |
| usage() | |
| main() |