[pve-devel] [PATCH qemu 3/7] buildsys: use QEMU's keycodemapdb again

Fiona Ebner f.ebner at proxmox.com
Thu Sep 28 14:59:22 CEST 2023


instead of the split-out version that was last updated for QEMU 6.0.
This reverts the relevant part of 6838f03 ("bump version to 2.11.1-1")
which doesn't state a reason why the splitting was done. If something
breaks, we can still re-do it and document the reason this time.

Alternatively, it would be necessary to adapt the paths, because
keycodemapdb lives in subprojects/ rather than ui/ since QEMU commit
c53648abba ("meson: use subproject for keycodemapdb").

Signed-off-by: Fiona Ebner <f.ebner at proxmox.com>
---
 Makefile                                     |   15 +-
 keycodemapdb/LICENSE.BSD                     |   27 -
 keycodemapdb/LICENSE.GPL2                    |  339 ---
 keycodemapdb/README                          |  114 -
 keycodemapdb/data/README                     |   89 -
 keycodemapdb/data/keymaps.csv                |  539 ----
 keycodemapdb/meson.build                     |    1 -
 keycodemapdb/tests/.gitignore                |   11 -
 keycodemapdb/tests/Makefile                  |  150 --
 keycodemapdb/tests/javascript                |   53 -
 keycodemapdb/tests/python2                   |    3 -
 keycodemapdb/tests/python3                   |    3 -
 keycodemapdb/tests/stdc++.cc                 |   40 -
 keycodemapdb/tests/stdc.c                    |   64 -
 keycodemapdb/tests/test.py                   |   30 -
 keycodemapdb/thirdparty/LICENSE-argparse.txt |   20 -
 keycodemapdb/thirdparty/__init__.py          |    0
 keycodemapdb/thirdparty/argparse.py          | 2392 ------------------
 keycodemapdb/tools/keymap-gen                | 1147 ---------
 19 files changed, 1 insertion(+), 5036 deletions(-)
 delete mode 100644 keycodemapdb/LICENSE.BSD
 delete mode 100644 keycodemapdb/LICENSE.GPL2
 delete mode 100644 keycodemapdb/README
 delete mode 100644 keycodemapdb/data/README
 delete mode 100644 keycodemapdb/data/keymaps.csv
 delete mode 100644 keycodemapdb/meson.build
 delete mode 100644 keycodemapdb/tests/.gitignore
 delete mode 100644 keycodemapdb/tests/Makefile
 delete mode 100755 keycodemapdb/tests/javascript
 delete mode 100755 keycodemapdb/tests/python2
 delete mode 100755 keycodemapdb/tests/python3
 delete mode 100644 keycodemapdb/tests/stdc++.cc
 delete mode 100644 keycodemapdb/tests/stdc.c
 delete mode 100644 keycodemapdb/tests/test.py
 delete mode 100644 keycodemapdb/thirdparty/LICENSE-argparse.txt
 delete mode 100644 keycodemapdb/thirdparty/__init__.py
 delete mode 100644 keycodemapdb/thirdparty/argparse.py
 delete mode 100755 keycodemapdb/tools/keymap-gen

diff --git a/Makefile b/Makefile
index e389a9c..cad130e 100644
--- a/Makefile
+++ b/Makefile
@@ -39,16 +39,14 @@ PC_BIOS_FW_PURGE_LIST_IN = \
 BLOB_PURGE_SED_CMDS = $(foreach FILE,$(PC_BIOS_FW_PURGE_LIST_IN),-e "/$(FILE)/d")
 BLOB_PURGE_FILTER = $(foreach FILE,$(PC_BIOS_FW_PURGE_LIST_IN),-e "$(FILE)")
 
-$(BUILDDIR): keycodemapdb | submodule
+$(BUILDDIR): submodule
 	# check if qemu/ was used for a build
 	# if so, please run 'make distclean' in the submodule and try again
 	test ! -f $(SRCDIR)/build/config.status
 	rm -rf $@.tmp $@
 	cp -a $(SRCDIR) $@.tmp
 	cp -a debian $@.tmp/debian
-	rm -rf $@.tmp/ui/keycodemapdb
 	rm -rf $@.tmp/roms/edk2 # packaged separately
-	cp -a keycodemapdb $@.tmp/ui/
 	find $@.tmp/pc-bios -type f | grep $(BLOB_PURGE_FILTER) | xargs rm -f
 	sed -i $(BLOB_PURGE_SED_CMDS) $@.tmp/pc-bios/meson.build
 	echo "git clone git://git.proxmox.com/git/pve-qemu.git\\ngit checkout $(GITVERSION)" > $@.tmp/debian/SOURCE
@@ -76,17 +74,6 @@ dsc:
 $(DSC): $(ORIG_SRC_TAR) $(BUILDDIR)
 	cd $(BUILDDIR); dpkg-buildpackage -S -us -uc -d
 
-.PHONY: update
-update:
-	cd $(SRCDIR) && git submodule deinit ui/keycodemapdb || true
-	rm -rf $(SRCDIR)/ui/keycodemapdb
-	mkdir $(SRCDIR)/ui/keycodemapdb
-	cd $(SRCDIR) && git submodule update --init ui/keycodemapdb
-	rm -rf keycodemapdb
-	mkdir keycodemapdb
-	cp -R $(SRCDIR)/ui/keycodemapdb/* keycodemapdb/
-	git add keycodemapdb
-
 .PHONY: upload
 upload: UPLOAD_DIST ?= $(DEB_DISTRIBUTION)
 upload: $(DEBS)
diff --git a/keycodemapdb/LICENSE.BSD b/keycodemapdb/LICENSE.BSD
deleted file mode 100644
index ec1a29d..0000000
--- a/keycodemapdb/LICENSE.BSD
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) Individual contributors.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    1. Redistributions of source code must retain the above copyright notice,
-       this list of conditions and the following disclaimer.
-
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in the
-       documentation and/or other materials provided with the distribution.
-
-    3. Neither the name of PyCA Cryptography nor the names of its contributors
-       may be used to endorse or promote products derived from this software
-       without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/keycodemapdb/LICENSE.GPL2 b/keycodemapdb/LICENSE.GPL2
deleted file mode 100644
index d511905..0000000
--- a/keycodemapdb/LICENSE.GPL2
+++ /dev/null
@@ -1,339 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/keycodemapdb/README b/keycodemapdb/README
deleted file mode 100644
index a3c3c9f..0000000
--- a/keycodemapdb/README
+++ /dev/null
@@ -1,114 +0,0 @@
-   Key code / scan code / key symbol mapping database
-   ==================================================
-
-This module provides a database that maps between different
-key code / scan code / key symbol sets:
-
- - Linux evdev
- - OS-X
- - AT Set 1
- - AT Set 2
- - AT Set 3
- - XT
- - Linux XT KBD driver
- - USB HID
- - Win32
- - XWin XT
- - XKBD XT
- - Xorg Evdev
- - Xorg KBD
- - Xorg OS-X
- - XOrg Cygwin
- - RFB
-
-Licensing
----------
-
-The contents of this package are dual licensed under the terms of:
-
- - GNU General Public License (version 2 or later)
- - 3-clause BSD License
-
-The output files generated by keymap-gen may be distributed & used under
-the terms of either of the above licenses.
-
-Data formats
-------------
-
-The following output formats are possible
-
- - Code map
-
-   An array mapping between key code sets values
-
-   Indexes in the array are values from the source code set.
-   Entries in the array are values from the target code set
-
-
- - Code table
-
-   An array listing all values in a key code set
-
-   Indexes in the array are simply a numeric counter
-   Entries in the array are values from the key code set
-
-   The size of the array matches the total number of entries in
-   the keycode database.
-
-
- - Name map
-
-   An array mapping between key code sets values and names
-
-   Indexes in the array are values from the source code set
-   Entries in the array are names from the target code set
-
-
- - Name table
-
-   An array listing all names in a key code set
-
-   Indexes in the array are simply a numeric counter
-   Entries in the array are values from the key code set
-
-   The size of the array matches the total number of entries in
-   the keycode database.
-
-
-Output languages
-----------------
-
-The tool is capable of generating data tables for the following
-programming languages / environments
-
- - Standard C
- - GLib2 (standard C, but with GLib2 data types)
- - Python
- - Perl
-
-
-Usage
------
-
-Map values from AT Set 1 to USB HID, generating tables for the
-C programming language
-
- $ keymap-gen --lang stdc code-map data/keymaps.csv atset1 usb
-
-Generate a tables of names for Linux key codes, OS-X key codes,
-in python - equivalent array indexes map between the two sets.
-A variable name override is used
-
- $ keymap-gen --varname linux_keycodes --lang stdc \
-              code-table data/keymaps.csv linux
- $ keymap-gen --varname osx_keycodes --lang stdc \
-              code-table data/keymaps.csv os-x
-
-Generate a mapping from XOrg XWin values to Win32 names
-
- $ keymap-gen --lang perl name-map data/keymaps.csv xorgxwin win32
-
-Generate a table of names for Linux key codes in Perl
-
- $ keymap-gen --lang perl name-table data/keymaps.csv linux
-
diff --git a/keycodemapdb/data/README b/keycodemapdb/data/README
deleted file mode 100644
index 6b56534..0000000
--- a/keycodemapdb/data/README
+++ /dev/null
@@ -1,89 +0,0 @@
-This directory contains the raw data for mapping between different
-keyboard codes. Naming if often based on the US keyboard layout, but
-does not indicate the symbol actually generated by the key.
-
-The columns currently in this data set are:
-
-Linux
------
-
-Name and value of the hardware independent keycodes used by the linux
-kernel and exposed through the input subsystem.
-
-References: linux/input.h
-
-macOS
------
-
-Low level key codes as exposed by Mac OS X/macOS.
-
-References: Carbon/HIToolbox/Events.h
-
-PC scan code sets
------------------
-
-Scan codes for the three orignal PC keyboard generations:
-
- Set 1: XT
- Set 2: AT
- Set 3: PS/2
-
-The sets include codes for modern keys as well and not just the keys
-present on those original keyboards.
-
-References: linux/drivers/input/keyboard/atkbd.c
-
-USB HID
--------
-
-Codes as specified by the HID profile in USB.
-
-References: linux/drivers/hid/usbhid/usbkbd.c
-
-Windows Virtual-key codes
--------------------------
-
-The low level, hardware independent "VKEYs" exposed by Windows.
-
-References: mingw32/winuser.h
-
-XWin XT
--------
-
-X11 keycodes generated by the XWin server. Based on the XT scan code
-set.
-
-References: xorg-server/hw/xwin/{winkeybd.c,winkeynames.h}
-
-Xfree86 KBD XT
---------------
-
-X11 keycodes generated by the Xfree86 keyboard drivers. Based on the XT
-scan code set.
-
-References: xf86-input-keyboard/src/at_scancode.c
-
-X11 keysyms
------------
-
-Corresponding X11 keysym value(s) for a US keyboard layout.
-
-WARNING: These columns represent symbols, not physical keys, and should
-         be used with extreme care.
-
-References: http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h
-
-HTML KeyboardEvent.code
------------------------
-
-Key codes seen in the KeyboardEvent.code attribute as part of the
-UI Events specification.
-
-References: https://www.w3.org/TR/uievents-code/
-
-XKEYBOARD key names
--------------------
-
-Hardware independent key names as used in the XKEYBOARD extension.
-
-References: /usr/share/X11/xkb/keycodes/
diff --git a/keycodemapdb/data/keymaps.csv b/keycodemapdb/data/keymaps.csv
deleted file mode 100644
index 6b1631e..0000000
--- a/keycodemapdb/data/keymaps.csv
+++ /dev/null
@@ -1,539 +0,0 @@
-"Linux Name","Linux Keycode","OS-X Name","OS-X Keycode","AT set1 keycode","AT set2 keycode","AT set3 keycode","USB Keycodes","Win32 Name","Win32 Keycode","Xwin XT","Xfree86 KBD XT","X11 keysym name","X11 keysym","HTML code","XKB key name","QEMU QKeyCode","Sun KBD","Apple ADB"
-KEY_RESERVED,0,,0xff,,,,,,,,,,,,,unmapped,,0xff
-KEY_ESC,1,Escape,0x35,0x01,0x76,0x08,41,VK_ESCAPE,0x1b,1,1,XK_Escape,0xff1b,Escape,ESC,esc,0x1d,0x35
-KEY_1,2,ANSI_1,0x12,0x02,0x16,0x16,30,VK_1,0x31,2,2,XK_1,0x0031,Digit1,AE01,1,0x1e,0x12
-KEY_1,2,ANSI_1,0x12,0x02,0x16,0x16,30,VK_1,0x31,2,2,XK_exclam,0x0021,Digit1,AE01,1,0x1e,0x12
-KEY_2,3,ANSI_2,0x13,0x03,0x1e,0x1e,31,VK_2,0x32,3,3,XK_2,0x0032,Digit2,AE02,2,0x1f,0x13
-KEY_2,3,ANSI_2,0x13,0x03,0x1e,0x1e,31,VK_2,0x32,3,3,XK_at,0x0040,Digit2,AE02,2,0x1f,0x13
-KEY_3,4,ANSI_3,0x14,0x04,0x26,0x26,32,VK_3,0x33,4,4,XK_3,0x0033,Digit3,AE03,3,0x20,0x14
-KEY_3,4,ANSI_3,0x14,0x04,0x26,0x26,32,VK_3,0x33,4,4,XK_numbersign,0x0023,Digit3,AE03,3,0x20,0x14
-KEY_4,5,ANSI_4,0x15,0x05,0x25,0x25,33,VK_4,0x34,5,5,XK_4,0x0034,Digit4,AE04,4,0x21,0x15
-KEY_4,5,ANSI_4,0x15,0x05,0x25,0x25,33,VK_4,0x34,5,5,XK_dollar,0x0024,Digit4,AE04,4,0x21,0x15
-KEY_5,6,ANSI_5,0x17,0x06,0x2e,0x2e,34,VK_5,0x35,6,6,XK_5,0x0035,Digit5,AE05,5,0x22,0x17
-KEY_5,6,ANSI_5,0x17,0x06,0x2e,0x2e,34,VK_5,0x35,6,6,XK_percent,0x0025,Digit5,AE05,5,0x22,0x17
-KEY_6,7,ANSI_6,0x16,0x07,0x36,0x36,35,VK_6,0x36,7,7,XK_6,0x0036,Digit6,AE06,6,0x23,0x16
-KEY_6,7,ANSI_6,0x16,0x07,0x36,0x36,35,VK_6,0x36,7,7,XK_asciicircum,0x005e,Digit6,AE06,6,0x23,0x16
-KEY_7,8,ANSI_7,0x1a,0x08,0x3d,0x3d,36,VK_7,0x37,8,8,XK_7,0x0037,Digit7,AE07,7,0x24,0x1a
-KEY_7,8,ANSI_7,0x1a,0x08,0x3d,0x3d,36,VK_7,0x37,8,8,XK_ampersand,0x0026,Digit7,AE07,7,0x24,0x1a
-KEY_8,9,ANSI_8,0x1c,0x09,0x3e,0x3e,37,VK_8,0x38,9,9,XK_8,0x0038,Digit8,AE08,8,0x25,0x1c
-KEY_8,9,ANSI_8,0x1c,0x09,0x3e,0x3e,37,VK_8,0x38,9,9,XK_asterisk,0x002a,Digit8,AE08,8,0x25,0x1c
-KEY_9,10,ANSI_9,0x19,0x0a,0x46,0x46,38,VK_9,0x39,10,10,XK_9,0x0039,Digit9,AE09,9,0x26,0x19
-KEY_9,10,ANSI_9,0x19,0x0a,0x46,0x46,38,VK_9,0x39,10,10,XK_parenleft,0x0028,Digit9,AE09,9,0x26,0x19
-KEY_0,11,ANSI_0,0x1d,0x0b,0x45,0x45,39,VK_0,0x30,11,11,XK_0,0x0030,Digit0,AE10,0,0x27,0x1d
-KEY_0,11,ANSI_0,0x1d,0x0b,0x45,0x45,39,VK_0,0x30,11,11,XK_parenright,0x0029,Digit0,AE10,0,0x27,0x1d
-KEY_MINUS,12,ANSI_Minus,0x1b,0x0c,0x4e,0x4e,45,VK_OEM_MINUS,0xbd,12,12,XK_minus,0x002d,Minus,AE11,minus,0x28,0x1b
-KEY_MINUS,12,ANSI_Minus,0x1b,0x0c,0x4e,0x4e,45,VK_OEM_MINUS,0xbd,12,12,XK_underscore,0x005f,Minus,AE11,minus,0x28,0x1b
-KEY_EQUAL,13,ANSI_Equal,0x18,0x0d,0x55,0x55,46,VK_OEM_PLUS,0xbb,13,13,XK_equal,0x003d,Equal,AE12,equal,0x29,0x18
-KEY_EQUAL,13,ANSI_Equal,0x18,0x0d,0x55,0x55,46,VK_OEM_PLUS,0xbb,13,13,XK_plus,0x002b,Equal,AE12,equal,0x29,0x18
-KEY_BACKSPACE,14,Delete,0x33,0x0e,0x66,0x66,42,VK_BACK,0x08,14,14,XK_BackSpace,0xff08,Backspace,BKSP,backspace,0x2b,0x33
-KEY_TAB,15,Tab,0x30,0x0f,0x0d,0x0d,43,VK_TAB,0x09,15,15,XK_Tab,0xff09,Tab,TAB,tab,0x35,0x30
-KEY_Q,16,ANSI_Q,0xc,0x10,0x15,0x15,20,VK_Q,0x51,16,16,XK_Q,0x0051,KeyQ,AD01,q,0x36,0xc
-KEY_Q,16,ANSI_Q,0xc,0x10,0x15,0x15,20,VK_Q,0x51,16,16,XK_q,0x0071,KeyQ,AD01,q,0x36,0xc
-KEY_W,17,ANSI_W,0xd,0x11,0x1d,0x1d,26,VK_W,0x57,17,17,XK_W,0x0057,KeyW,AD02,w,0x37,0xd
-KEY_W,17,ANSI_W,0xd,0x11,0x1d,0x1d,26,VK_W,0x57,17,17,XK_w,0x0077,KeyW,AD02,w,0x37,0xd
-KEY_E,18,ANSI_E,0xe,0x12,0x24,0x24,8,VK_E,0x45,18,18,XK_E,0x0045,KeyE,AD03,e,0x38,0xe
-KEY_E,18,ANSI_E,0xe,0x12,0x24,0x24,8,VK_E,0x45,18,18,XK_e,0x0065,KeyE,AD03,e,0x38,0xe
-KEY_R,19,ANSI_R,0xf,0x13,0x2d,0x2d,21,VK_R,0x52,19,19,XK_R,0x0052,KeyR,AD04,r,0x39,0xf
-KEY_R,19,ANSI_R,0xf,0x13,0x2d,0x2d,21,VK_R,0x52,19,19,XK_r,0x0072,KeyR,AD04,r,0x39,0xf
-KEY_T,20,ANSI_T,0x11,0x14,0x2c,0x2c,23,VK_T,0x54,20,20,XK_T,0x0054,KeyT,AD05,t,0x3a,0x11
-KEY_T,20,ANSI_T,0x11,0x14,0x2c,0x2c,23,VK_T,0x54,20,20,XK_t,0x0074,KeyT,AD05,t,0x3a,0x11
-KEY_Y,21,ANSI_Y,0x10,0x15,0x35,0x35,28,VK_Y,0x59,21,21,XK_Y,0x0059,KeyY,AD06,y,0x3b,0x10
-KEY_Y,21,ANSI_Y,0x10,0x15,0x35,0x35,28,VK_Y,0x59,21,21,XK_y,0x0079,KeyY,AD06,y,0x3b,0x10
-KEY_U,22,ANSI_U,0x20,0x16,0x3c,0x3c,24,VK_U,0x55,22,22,XK_U,0x0055,KeyU,AD07,u,0x3c,0x20
-KEY_U,22,ANSI_U,0x20,0x16,0x3c,0x3c,24,VK_U,0x55,22,22,XK_u,0x0075,KeyU,AD07,u,0x3c,0x20
-KEY_I,23,ANSI_I,0x22,0x17,0x43,0x43,12,VK_I,0x49,23,23,XK_I,0x0049,KeyI,AD08,i,0x3d,0x22
-KEY_I,23,ANSI_I,0x22,0x17,0x43,0x43,12,VK_I,0x49,23,23,XK_i,0x0069,KeyI,AD08,i,0x3d,0x22
-KEY_O,24,ANSI_O,0x1f,0x18,0x44,0x44,18,VK_O,0x4f,24,24,XK_O,0x004f,KeyO,AD09,o,0x3e,0x1f
-KEY_O,24,ANSI_O,0x1f,0x18,0x44,0x44,18,VK_O,0x4f,24,24,XK_o,0x006f,KeyO,AD09,o,0x3e,0x1f
-KEY_P,25,ANSI_P,0x23,0x19,0x4d,0x4d,19,VK_P,0x50,25,25,XK_P,0x0050,KeyP,AD10,p,0x3f,0x23
-KEY_P,25,ANSI_P,0x23,0x19,0x4d,0x4d,19,VK_P,0x50,25,25,XK_p,0x0070,KeyP,AD10,p,0x3f,0x23
-KEY_LEFTBRACE,26,ANSI_LeftBracket,0x21,0x1a,0x54,0x54,47,VK_OEM_4,0xdb,26,26,XK_bracketleft,0x005b,BracketLeft,AD11,bracket_left,0x40,0x21
-KEY_LEFTBRACE,26,ANSI_LeftBracket,0x21,0x1a,0x54,0x54,47,VK_OEM_4,0xdb,26,26,XK_braceleft,0x007b,BracketLeft,AD11,bracket_left,0x40,0x21
-KEY_RIGHTBRACE,27,ANSI_RightBracket,0x1e,0x1b,0x5b,0x5b,48,VK_OEM_6,0xdd,27,27,XK_bracketright,0x005d,BracketRight,AD12,bracket_right,0x41,0x1e
-KEY_RIGHTBRACE,27,ANSI_RightBracket,0x1e,0x1b,0x5b,0x5b,48,VK_OEM_6,0xdd,27,27,XK_braceright,0x007d,BracketRight,AD12,bracket_right,0x41,0x1e
-KEY_ENTER,28,Return,0x24,0x1c,0x5a,0x5a,40,VK_RETURN,0x0d,28,28,XK_Return,0xff0d,Enter,RTRN,ret,0x59,0x24
-KEY_LEFTCTRL,29,Control,0x3b,0x1d,0x14,0x11,224,VK_LCONTROL,0xa2,29,29,XK_Control_L,0xffe3,ControlLeft,LCTL,ctrl,0x4c,0x36
-KEY_LEFTCTRL,29,Control,0x3b,0x1d,0x14,0x11,224,VK_CONTROL,0x11,29,29,XK_Control_L,0xffe3,ControlLeft,LCTL,ctrl,0x4c,0x36
-KEY_A,30,ANSI_A,0x0,0x1e,0x1c,0x1c,4,VK_A,0x41,30,30,XK_A,0x0041,KeyA,AC01,a,0x4d,0x0
-KEY_A,30,ANSI_A,0x0,0x1e,0x1c,0x1c,4,VK_A,0x41,30,30,XK_a,0x0061,KeyA,AC01,a,0x4d,0x0
-KEY_S,31,ANSI_S,0x1,0x1f,0x1b,0x1b,22,VK_S,0x53,31,31,XK_S,0x0053,KeyS,AC02,s,0x4e,0x1
-KEY_S,31,ANSI_S,0x1,0x1f,0x1b,0x1b,22,VK_S,0x53,31,31,XK_s,0x0073,KeyS,AC02,s,0x4e,0x1
-KEY_D,32,ANSI_D,0x2,0x20,0x23,0x23,7,VK_D,0x44,32,32,XK_D,0x0044,KeyD,AC03,d,0x4f,0x2
-KEY_D,32,ANSI_D,0x2,0x20,0x23,0x23,7,VK_D,0x44,32,32,XK_d,0x0064,KeyD,AC03,d,0x4f,0x2
-KEY_F,33,ANSI_F,0x3,0x21,0x2b,0x2b,9,VK_F,0x46,33,33,XK_F,0x0046,KeyF,AC04,f,0x50,0x3
-KEY_F,33,ANSI_F,0x3,0x21,0x2b,0x2b,9,VK_F,0x46,33,33,XK_f,0x0066,KeyF,AC04,f,0x50,0x3
-KEY_G,34,ANSI_G,0x5,0x22,0x34,0x34,10,VK_G,0x47,34,34,XK_G,0x0047,KeyG,AC05,g,0x51,0x5
-KEY_G,34,ANSI_G,0x5,0x22,0x34,0x34,10,VK_G,0x47,34,34,XK_g,0x0067,KeyG,AC05,g,0x51,0x5
-KEY_H,35,ANSI_H,0x4,0x23,0x33,0x33,11,VK_H,0x48,35,35,XK_H,0x0048,KeyH,AC06,h,0x52,0x4
-KEY_H,35,ANSI_H,0x4,0x23,0x33,0x33,11,VK_H,0x48,35,35,XK_h,0x0068,KeyH,AC06,h,0x52,0x4
-KEY_J,36,ANSI_J,0x26,0x24,0x3b,0x3b,13,VK_J,0x4a,36,36,XK_J,0x004a,KeyJ,AC07,j,0x53,0x26
-KEY_J,36,ANSI_J,0x26,0x24,0x3b,0x3b,13,VK_J,0x4a,36,36,XK_j,0x006a,KeyJ,AC07,j,0x53,0x26
-KEY_K,37,ANSI_K,0x28,0x25,0x42,0x42,14,VK_K,0x4b,37,37,XK_K,0x004b,KeyK,AC08,k,0x54,0x28
-KEY_K,37,ANSI_K,0x28,0x25,0x42,0x42,14,VK_K,0x4b,37,37,XK_k,0x006b,KeyK,AC08,k,0x54,0x28
-KEY_L,38,ANSI_L,0x25,0x26,0x4b,0x4b,15,VK_L,0x4c,38,38,XK_L,0x004c,KeyL,AC09,l,0x55,0x25
-KEY_L,38,ANSI_L,0x25,0x26,0x4b,0x4b,15,VK_L,0x4c,38,38,XK_l,0x006c,KeyL,AC09,l,0x55,0x25
-KEY_SEMICOLON,39,ANSI_Semicolon,0x29,0x27,0x4c,0x4c,51,VK_OEM_1,0xba,39,39,XK_semicolon,0x003b,Semicolon,AC10,semicolon,0x56,0x29
-KEY_SEMICOLON,39,ANSI_Semicolon,0x29,0x27,0x4c,0x4c,51,VK_OEM_1,0xba,39,39,XK_colon,0x003a,Semicolon,AC10,semicolon,0x56,0x29
-KEY_APOSTROPHE,40,ANSI_Quote,0x27,0x28,0x52,0x52,52,VK_OEM_7,0xde,40,40,XK_apostrophe,0x0027,Quote,AC11,apostrophe,0x57,0x27
-KEY_APOSTROPHE,40,ANSI_Quote,0x27,0x28,0x52,0x52,52,VK_OEM_7,0xde,40,40,XK_quotedbl,0x0022,Quote,AC11,apostrophe,0x57,0x27
-KEY_GRAVE,41,ANSI_Grave,0x32,0x29,0x0e,0x0e,53,VK_OEM_3,0xc0,41,41,XK_grave,0x0060,Backquote,TLDE,grave_accent,0x2a,0x32
-KEY_GRAVE,41,ANSI_Grave,0x32,0x29,0x0e,0x0e,53,VK_OEM_3,0xc0,41,41,XK_grave,0x0060,Backquote,AB00,grave_accent,0x2a,0x32
-KEY_GRAVE,41,ANSI_Grave,0x32,0x29,0x0e,0x0e,53,VK_OEM_3,0xc0,41,41,XK_asciitilde,0x007e,Backquote,TLDE,grave_accent,0x2a,0x32
-KEY_GRAVE,41,ANSI_Grave,0x32,0x29,0x0e,0x0e,53,VK_OEM_3,0xc0,41,41,XK_asciitilde,0x007e,Backquote,AB00,grave_accent,0x2a,0x32
-KEY_SHIFT,42,Shift,0x38,0x2a,0x12,0x12,225,VK_SHIFT,0x10,42,42,XK_Shift_L,0xffe1,ShiftLeft,LFSH,shift,0x63,0x38
-KEY_LEFTSHIFT,42,Shift,0x38,0x2a,0x12,0x12,225,VK_LSHIFT,0xa0,42,42,XK_Shift_L,0xffe1,ShiftLeft,LFSH,shift,0x63,0x38
-KEY_BACKSLASH,43,ANSI_Backslash,0x2a,0x2b,0x5d,0x5c,49,VK_OEM_5,0xdc,43,43,XK_backslash,0x005c,Backslash,BKSL,backslash,0x58,0x2a
-KEY_BACKSLASH,43,ANSI_Backslash,0x2a,0x2b,0x5d,0x5c,49,VK_OEM_5,0xdc,43,43,XK_backslash,0x005c,Backslash,AC12,backslash,0x58,0x2a
-KEY_BACKSLASH,43,ANSI_Backslash,0x2a,0x2b,0x5d,0x5c,49,VK_OEM_5,0xdc,43,43,XK_bar,0x007c,Backslash,BKSL,backslash,0x58,0x2a
-KEY_BACKSLASH,43,ANSI_Backslash,0x2a,0x2b,0x5d,0x5c,49,VK_OEM_5,0xdc,43,43,XK_bar,0x007c,Backslash,AC12,backslash,0x58,0x2a
-KEY_BACKSLASH,43,ANSI_Backslash,0x2a,0x2b,0x5d,0x5c,50,VK_OEM_5,0xdc,43,43,XK_backslash,0x005c,Backslash,BKSL,backslash,0x58,0x2a
-KEY_BACKSLASH,43,ANSI_Backslash,0x2a,0x2b,0x5d,0x5c,50,VK_OEM_5,0xdc,43,43,XK_backslash,0x005c,Backslash,AC12,backslash,0x58,0x2a
-KEY_BACKSLASH,43,ANSI_Backslash,0x2a,0x2b,0x5d,0x5c,50,VK_OEM_5,0xdc,43,43,XK_bar,0x007c,Backslash,BKSL,backslash,0x58,0x2a
-KEY_BACKSLASH,43,ANSI_Backslash,0x2a,0x2b,0x5d,0x5c,50,VK_OEM_5,0xdc,43,43,XK_bar,0x007c,Backslash,AC12,backslash,0x58,0x2a
-KEY_Z,44,ANSI_Z,0x6,0x2c,0x1a,0x1a,29,VK_Z,0x5a,44,44,XK_Z,0x005a,KeyZ,AB01,z,0x64,0x6
-KEY_Z,44,ANSI_Z,0x6,0x2c,0x1a,0x1a,29,VK_Z,0x5a,44,44,XK_z,0x007a,KeyZ,AB01,z,0x64,0x6
-KEY_X,45,ANSI_X,0x7,0x2d,0x22,0x22,27,VK_X,0x58,45,45,XK_X,0x0058,KeyX,AB02,x,0x65,0x7
-KEY_X,45,ANSI_X,0x7,0x2d,0x22,0x22,27,VK_X,0x58,45,45,XK_x,0x0078,KeyX,AB02,x,0x65,0x7
-KEY_C,46,ANSI_C,0x8,0x2e,0x21,0x21,6,VK_C,0x43,46,46,XK_C,0x0043,KeyC,AB03,c,0x66,0x8
-KEY_C,46,ANSI_C,0x8,0x2e,0x21,0x21,6,VK_C,0x43,46,46,XK_c,0x0063,KeyC,AB03,c,0x66,0x8
-KEY_V,47,ANSI_V,0x9,0x2f,0x2a,0x2a,25,VK_V,0x56,47,47,XK_V,0x0056,KeyV,AB04,v,0x67,0x9
-KEY_V,47,ANSI_V,0x9,0x2f,0x2a,0x2a,25,VK_V,0x56,47,47,XK_v,0x0076,KeyV,AB04,v,0x67,0x9
-KEY_B,48,ANSI_B,0xb,0x30,0x32,0x32,5,VK_B,0x42,48,48,XK_B,0x0042,KeyB,AB05,b,0x68,0xb
-KEY_B,48,ANSI_B,0xb,0x30,0x32,0x32,5,VK_B,0x42,48,48,XK_b,0x0062,KeyB,AB05,b,0x68,0xb
-KEY_N,49,ANSI_N,0x2d,0x31,0x31,0x31,17,VK_N,0x4e,49,49,XK_N,0x004e,KeyN,AB06,n,0x69,0x2d
-KEY_N,49,ANSI_N,0x2d,0x31,0x31,0x31,17,VK_N,0x4e,49,49,XK_n,0x006e,KeyN,AB06,n,0x69,0x2d
-KEY_M,50,ANSI_M,0x2e,0x32,0x3a,0x3a,16,VK_M,0x4d,50,50,XK_M,0x004d,KeyM,AB07,m,0x6a,0x2e
-KEY_M,50,ANSI_M,0x2e,0x32,0x3a,0x3a,16,VK_M,0x4d,50,50,XK_m,0x006d,KeyM,AB07,m,0x6a,0x2e
-KEY_COMMA,51,ANSI_Comma,0x2b,0x33,0x41,0x41,54,VK_OEM_COMMA,0xbc,51,51,XK_comma,0x002c,Comma,AB08,comma,0x6b,0x2b
-KEY_COMMA,51,ANSI_Comma,0x2b,0x33,0x41,0x41,54,VK_OEM_COMMA,0xbc,51,51,XK_less,0x003c,Comma,AB08,comma,0x6b,0x2b
-KEY_DOT,52,ANSI_Period,0x2f,0x34,0x49,0x49,55,VK_OEM_PERIOD,0xbe,52,52,XK_period,0x002e,Period,AB09,dot,0x6c,0x2f
-KEY_DOT,52,ANSI_Period,0x2f,0x34,0x49,0x49,55,VK_OEM_PERIOD,0xbe,52,52,XK_greater,0x003e,Period,AB09,dot,0x6c,0x2f
-KEY_SLASH,53,ANSI_Slash,0x2c,0x35,0x4a,0x4a,56,VK_OEM_2,0xbf,53,53,XK_slash,0x002f,Slash,AB10,slash,0x6d,0x2c
-KEY_SLASH,53,ANSI_Slash,0x2c,0x35,0x4a,0x4a,56,VK_OEM_2,0xbf,53,53,XK_question,0x003f,Slash,AB10,slash,0x6d,0x2c
-KEY_RIGHTSHIFT,54,RightShift,0x3c,0x36,0x59,0x59,229,VK_RSHIFT,0xa1,54,54,XK_Shift_R,0xffe2,ShiftRight,RTSH,shift_r,0x6e,0x7b
-KEY_KPASTERISK,55,ANSI_KeypadMultiply,0x43,0x37,0x7c,0x7e,85,VK_MULTIPLY,0x6a,55,55,XK_multiply,0x00d7,NumpadMultiply,KPMU,asterisk,0x2f,0x43
-KEY_KPASTERISK,55,ANSI_KeypadMultiply,0x43,0x37,0x7c,0x7e,85,VK_MULTIPLY,0x6a,55,55,XK_multiply,0x00d7,NumpadMultiply,KPMU,kp_multiply,0x2f,0x43
-KEY_LEFTALT,56,Option,0x3a,0x38,0x11,0x19,226,VK_LMENU,0xa4,56,56,XK_Alt_L,0xffe9,AltLeft,LALT,alt,0x13,0x3a
-KEY_LEFTALT,56,Option,0x3a,0x38,0x11,0x19,226,VK_MENU,0x12,56,56,XK_Alt_L,0xffe9,AltLeft,LALT,alt,0x13,0x3a
-KEY_SPACE,57,Space,0x31,0x39,0x29,0x29,44,VK_SPACE,0x20,57,57,XK_space,0x0020,Space,SPCE,spc,0x79,0x31
-KEY_CAPSLOCK,58,CapsLock,0x39,0x3a,0x58,0x14,57,VK_CAPITAL,0x14,58,58,XK_Caps_Lock,0xffe5,CapsLock,CAPS,caps_lock,0x77,0x39
-KEY_F1,59,F1,0x7a,0x3b,0x05,0x07,58,VK_F1,0x70,59,59,XK_F1,0xffbe,F1,FK01,f1,0x05,0x7a
-KEY_F2,60,F2,0x78,0x3c,0x06,0x0f,59,VK_F2,0x71,60,60,XK_F2,0xffbf,F2,FK02,f2,0x06,0x78
-KEY_F3,61,F3,0x63,0x3d,0x04,0x17,60,VK_F3,0x72,61,61,XK_F3,0xffc0,F3,FK03,f3,0x08,0x63
-KEY_F4,62,F4,0x76,0x3e,0x0c,0x1f,61,VK_F4,0x73,62,62,XK_F4,0xffc1,F4,FK04,f4,0x0a,0x76
-KEY_F5,63,F5,0x60,0x3f,0x03,0x27,62,VK_F5,0x74,63,63,XK_F5,0xffc2,F5,FK05,f5,0x0c,0x60
-KEY_F6,64,F6,0x61,0x40,0x0b,0x2f,63,VK_F6,0x75,64,64,XK_F6,0xffc3,F6,FK06,f6,0x0e,0x61
-KEY_F7,65,F7,0x62,0x41,0x83,0x37,64,VK_F7,0x76,65,65,XK_F7,0xffc4,F7,FK07,f7,0x10,0x62
-KEY_F8,66,F8,0x64,0x42,0x0a,0x3f,65,VK_F8,0x77,66,66,XK_F8,0xffc5,F8,FK08,f8,0x11,0x64
-KEY_F9,67,F9,0x65,0x43,0x01,0x47,66,VK_F9,0x78,67,67,XK_F9,0xffc6,F9,FK09,f9,0x12,0x65
-KEY_F10,68,F10,0x6d,0x44,0x09,0x4f,67,VK_F10,0x79,68,68,XK_F10,0xffc7,F10,FK10,f10,0x07,0x6d
-KEY_NUMLOCK,69,ANSI_KeypadClear,0x47,0x45,0x77,0x76,83,VK_NUMLOCK,0x90,69,69,XK_Num_Lock,0xff7f,NumLock,NMLK,num_lock,0x62,0x47
-KEY_SCROLLLOCK,70,,,0x46,0x7e,0x5f,71,VK_SCROLL,0x91,70,70,XK_Scroll_Lock,0xff14,ScrollLock,SCLK,scroll_lock,0x17,0x6b
-KEY_KP7,71,ANSI_Keypad7,0x59,0x47,0x6c,0x6c,95,VK_NUMPAD7,0x67,71,71,XK_KP_7,0xffb7,Numpad7,KP7,kp_7,0x44,0x59
-KEY_KP8,72,ANSI_Keypad8,0x5b,0x48,0x75,0x75,96,VK_NUMPAD8,0x68,72,72,XK_KP_8,0xffb8,Numpad8,KP8,kp_8,0x45,0x5b
-KEY_KP9,73,ANSI_Keypad9,0x5c,0x49,0x7d,0x7d,97,VK_NUMPAD9,0x69,73,73,XK_KP_9,0xffb9,Numpad9,KP9,kp_9,0x46,0x5c
-KEY_KPMINUS,74,ANSI_KeypadMinus,0x4e,0x4a,0x7b,0x4e,86,VK_SUBTRACT,0x6d,74,74,XK_KP_Subtract,0xffad,NumpadSubtract,KPSU,kp_subtract,0x47,0x4e
-KEY_KP4,75,ANSI_Keypad4,0x56,0x4b,0x6b,0x6b,92,VK_NUMPAD4,0x64,75,75,XK_KP_4,0xffb4,Numpad4,KP4,kp_4,0x5b,0x56
-KEY_KP5,76,ANSI_Keypad5,0x57,0x4c,0x73,0x73,93,VK_NUMPAD5,0x65,76,76,XK_KP_5,0xffb5,Numpad5,KP5,kp_5,0x5c,0x57
-KEY_KP6,77,ANSI_Keypad6,0x58,0x4d,0x74,0x74,94,VK_NUMPAD6,0x66,77,77,XK_KP_6,0xffb6,Numpad6,KP6,kp_6,0x5d,0x58
-KEY_KPPLUS,78,ANSI_KeypadPlus,0x45,0x4e,0x79,0x7c,87,VK_ADD,0x6b,78,78,XK_KP_Add,0xffab,NumpadAdd,KPAD,kp_add,0x7d,0x45
-KEY_KP1,79,ANSI_Keypad1,0x53,0x4f,0x69,0x69,89,VK_NUMPAD1,0x61,79,79,XK_KP_1,0xffb1,Numpad1,KP1,kp_1,0x70,0x53
-KEY_KP2,80,ANSI_Keypad2,0x54,0x50,0x72,0x72,90,VK_NUMPAD2,0x62,80,80,XK_KP_2,0xffb2,Numpad2,KP2,kp_2,0x71,0x54
-KEY_KP3,81,ANSI_Keypad3,0x55,0x51,0x7a,0x7a,91,VK_NUMPAD3,0x63,81,81,XK_KP_3,0xffb3,Numpad3,KP3,kp_3,0x72,0x55
-KEY_KP0,82,ANSI_Keypad0,0x52,0x52,0x70,0x70,98,VK_NUMPAD0,0x60,82,82,XK_KP_0,0xffb0,Numpad0,KP0,kp_0,0x5e,0x52
-KEY_KPDOT,83,ANSI_KeypadDecimal,0x41,0x53,0x71,0x71,99,VK_DECIMAL,0x6e,83,83,XK_KP_Decimal,0xffae,NumpadDecimal,KPDL,kp_decimal,0x32,0x41
-KEY_KPDOT,83,ANSI_KeypadDecimal,0x41,0x53,0x71,0x71,99,VK_DECIMAL,0x6e,83,83,XK_KP_Decimal,0xffae,NumpadDecimal,KPDC,kp_decimal,0x32,0x41
-,84,,,0x54,,,,,,,,,,,,,,
-KEY_ZENKAKUHANKAKU,85,,,0x76,0x5f,,148,,,,,,,Lang5,HZTG,,,
-KEY_102ND,86,,,0x56,0x61,0x13,100,VK_OEM_102,0xe2,86,86,,,IntlBackslash,LSGT,less,0x7c,
-KEY_F11,87,F11,0x67,0x57,0x78,0x56,68,VK_F11,0x7a,87,87,XK_F11,0xffc8,F11,FK11,f11,0x09,0x67
-KEY_F12,88,F12,0x6f,0x58,0x07,0x5e,69,VK_F12,0x7b,88,88,XK_F12,0xffc9,F12,FK12,f12,0x0b,0x6f
-KEY_RO,89,JIS_Underscore,0x5e,0x73,0x51,,135,,,,,,,IntlRo,AB11,ro,,
-KEY_KATAKANA,90,,,0x78,0x63,,146,VK_KANA,0x15,,,,,Katakana,KATA,,,
-KEY_KATAKANA,90,,,0x78,0x63,,146,VK_KANA,0x15,,,,,Lang3,KATA,,,
-KEY_HIRAGANA,91,,,0x77,0x62,0x87,147,,,,,,,Hiragana,HIRA,hiragana,,
-KEY_HIRAGANA,91,,,0x77,0x62,0x87,147,,,,,,,Lang4,HIRA,hiragana,,
-KEY_HENKAN,92,,,0x79,0x64,0x86,138,,,,,,,Convert,HENK,henkan,,
-KEY_KATAKANAHIRAGANA,93,,,0x70,0x13,0x87,136,,,0xc8,0xc8,,,KanaMode,HKTG,katakanahiragana,,
-KEY_MUHENKAN,94,,,0x7b,0x67,0x85,139,,,,,,,NonConvert,NFER,muhenkan,,
-KEY_MUHENKAN,94,,,0x7b,0x67,0x85,139,,,,,,,NonConvert,MUHE,muhenkan,,
-KEY_KPJPCOMMA,95,JIS_KeypadComma,0x5f,0x5c,0x27,,140,,,,,XK_KP_Separator,0xffac,,KPSP,,,
-KEY_KPJPCOMMA,95,JIS_KeypadComma,0x5f,0x5c,0x27,,140,,,,,XK_KP_Separator,0xffac,,JPCM,,,
-KEY_KPENTER,96,ANSI_KeypadEnter,0x4c,0xe01c,0xe05a,0x79,88,,,0x64,0x64,XK_KP_Enter,0xff8d,NumpadEnter,KPEN,kp_enter,0x5a,0x4c
-KEY_RIGHTCTRL,97,RightControl,0x3e,0xe01d,0xe014,0x58,228,VK_RCONTROL,0xa3,0x65,0x65,XK_Control_R,0xffe4,ControlRight,RCTL,ctrl_r,0x4c,0x7d
-KEY_KPSLASH,98,ANSI_KeypadDivide,0x4b,0xe035,0xe04a,0x4a,84,VK_DIVIDE,0x6f,0x68,0x68,XK_KP_Divide,0xffaf,NumpadDivide,KPDV,kp_divide,0x2e,0x4b
-KEY_SYSRQ,99,,,0x54,0x7f,0x57,70,VK_SNAPSHOT,0x2c,0x67,0x67,XK_Sys_Req,0xff15,PrintScreen,PRSC,print,0x16,0x69
-KEY_SYSRQ,99,,,0x54,0x7f,0x57,70,VK_SNAPSHOT,0x2c,0x67,0x67,XK_Sys_Req,0xff15,PrintScreen,SYRQ,sysrq,0x16,0x69
-KEY_RIGHTALT,100,RightOption,0x3d,0xe038,0xe011,0x39,230,VK_RMENU,0xa5,0x69,0x69,XK_Alt_R,0xffea,AltRight,ALGR,alt_r,0x0d,0x7c
-KEY_RIGHTALT,100,RightOption,0x3d,0xe038,0xe011,0x39,230,VK_RMENU,0xa5,0x69,0x69,XK_Alt_R,0xffea,AltRight,RALT,alt_r,0x0d,0x7c
-KEY_LINEFEED,101,,,0x5b,,,,,,,,,,,LNFD,lf,0x6f,
-KEY_HOME,102,Home,0x73,0xe047,0xe06c,0x6e,74,VK_HOME,0x24,0x59,0x59,XK_Home,0xff50,Home,HOME,home,0x34,0x73
-KEY_UP,103,UpArrow,0x7e,0xe048,0xe075,0x63,82,VK_UP,0x26,0x5a,0x5a,XK_Up,0xff52,ArrowUp,UP,up,0x14,0x3e
-KEY_PAGEUP,104,PageUp,0x74,0xe049,0xe07d,0x6f,75,VK_PRIOR,0x21,0x5b,0x5b,XK_Page_Up,0xff55,PageUp,PGUP,pgup,0x60,0x74
-KEY_LEFT,105,LeftArrow,0x7b,0xe04b,0xe06b,0x61,80,VK_LEFT,0x25,0x5c,0x5c,XK_Left,0xff51,ArrowLeft,LEFT,left,0x18,0x3b
-KEY_RIGHT,106,RightArrow,0x7c,0xe04d,0xe074,0x6a,79,VK_RIGHT,0x27,0x5e,0x5e,XK_Right,0xff53,ArrowRight,RGHT,right,0x1c,0x3c
-KEY_END,107,End,0x77,0xe04f,0xe069,0x65,77,VK_END,0x23,0x5f,0x5f,XK_End,0xff57,End,END,end,0x4a,0x77
-KEY_DOWN,108,DownArrow,0x7d,0xe050,0xe072,0x60,81,VK_DOWN,0x28,0x60,0x60,XK_Down,0xff54,ArrowDown,DOWN,down,0x1b,0x3d
-KEY_PAGEDOWN,109,PageDown,0x79,0xe051,0xe07a,0x6d,78,VK_NEXT,0x22,0x61,0x61,XK_Page_Down,0xff56,PageDown,PGDN,pgdn,0x7b,0x79
-KEY_INSERT,110,,,0xe052,0xe070,0x67,73,VK_INSERT,0x2d,0x62,0x62,XK_Insert,0xff63,Insert,INS,insert,0x2c,0x72
-KEY_DELETE,111,ForwardDelete,0x75,0xe053,0xe071,0x64,76,VK_DELETE,0x2e,0x63,0x63,XK_Delete,0xffff,Delete,DEL,delete,0x42,0x75
-KEY_DELETE,111,ForwardDelete,0x75,0xe053,0xe071,0x64,76,VK_DELETE,0x2e,0x63,0x63,XK_Delete,0xffff,Delete,DELE,,0x42,0x75
-KEY_MACRO,112,,,0xe06f,0xe06f,0x8e,,,,,,,,,I120,,,
-KEY_MUTE,113,Mute,0x4a,0xe020,0xe023,0x9c,127,VK_VOLUME_MUTE,0xad,,,,,AudioVolumeMute,MUTE,audiomute,,
-KEY_MUTE,113,Mute,0x4a,0xe020,0xe023,0x9c,239,VK_VOLUME_MUTE,0xad,,,,,AudioVolumeMute,MUTE,audiomute,,
-KEY_VOLUMEDOWN,114,VolumeDown,0x49,0xe02e,0xe021,0x9d,129,VK_VOLUME_DOWN,0xae,,,,,AudioVolumeDown,VOL-,volumedown,,
-KEY_VOLUMEDOWN,114,VolumeDown,0x49,0xe02e,0xe021,0x9d,238,VK_VOLUME_DOWN,0xae,,,,,AudioVolumeDown,VOL-,volumedown,,
-KEY_VOLUMEUP,115,VolumeUp,0x48,0xe030,0xe032,0x95,128,VK_VOLUME_UP,0xaf,,,,,AudioVolumeUp,VOL+,volumeup,,
-KEY_VOLUMEUP,115,VolumeUp,0x48,0xe030,0xe032,0x95,237,VK_VOLUME_UP,0xaf,,,,,AudioVolumeUp,VOL+,volumeup,,
-KEY_POWER,116,,,0xe05e,0xe037,,102,,,,,,,Power,POWR,power,,0x7f7f
-KEY_KPEQUAL,117,ANSI_KeypadEquals,0x51,0x59,0x0f,,103,,,0x76,0x76,XK_KP_Equal,0xffbd,NumpadEqual,KPEQ,kp_equals,0x2d,0x51
-KEY_KPPLUSMINUS,118,,,0xe04e,0xe079,,,,,,,,,,I126,,,
-KEY_PAUSE,119,,,0xe046,0xe077,0x62,72,VK_PAUSE,0x013,0x66,0x66,XK_Pause,0xff13,Pause,PAUS,pause,0x15,0x71
-KEY_SCALE,120,,,0xe00b,,,,,,,,,,,I128,,,
-KEY_KPCOMMA,121,,,0x7e,0x6d,,133,VK_SEPARATOR??,0x6c,,,,,NumpadComma,KPCO,kp_comma,,
-KEY_KPCOMMA,121,,,0x7e,0x6d,,133,VK_SEPARATOR??,0x6c,,,,,NumpadComma,I129,,,
-KEY_HANGEUL,122,JIS_Kana,0x68,0x72,,,144,VK_HANGEUL,0x15,,0x71,,,Lang1,HNGL,,,
-KEY_HANJA,123,JIS_Eisu,0x66,0x71,,,145,VK_HANJA,0x19,,0x72,,,Lang2,HJCV,,,
-KEY_YEN,124,JIS_Yen,0x5d,0x7d,0x6a,0x5d,137,,,0x7d,0x7d,,,IntlYen,AE13,yen,,
-KEY_LEFTMETA,125,Command,0x37,0xe05b,0xe01f,0x8b,227,VK_LWIN,0x5b,0x6b,0x6b,XK_Meta_L,0xffe7,MetaLeft,LMTA,meta_l,0x78,0x37
-KEY_LEFTMETA,125,Command,0x37,0xe05b,0xe01f,0x8b,227,VK_LWIN,0x5b,0x6b,0x6b,XK_Meta_L,0xffe7,MetaLeft,LWIN,meta_l,0x78,0x37
-KEY_RIGHTMETA,126,RightCommand,0x36,0xe05c,0xe027,0x8c,231,VK_RWIN,0x5c,0x6c,0x6c,XK_Meta_R,0xffe8,MetaRight,RMTA,meta_r,0x7a,0x37
-KEY_RIGHTMETA,126,RightCommand,0x36,0xe05c,0xe027,0x8c,231,VK_RWIN,0x5c,0x6c,0x6c,XK_Meta_R,0xffe8,MetaRight,RWIN,meta_r,0x7a,0x37
-KEY_COMPOSE,127,,0x6e,0xe05d,0xe02f,0x8d,101,VK_APPS,0x5d,0x6d,0x6d,,,ContextMenu,MENU,compose,0x43,
-KEY_COMPOSE,127,,0x6e,0xe05d,0xe02f,0x8d,101,VK_APPS,0x5d,0x6d,0x6d,,,ContextMenu,COMP,compose,0x43,
-KEY_STOP,128,,,0xe068,0xe028,0x0a,120,VK_BROWSER_STOP,0xa9,,,,,BrowserStop,STOP,stop,0x01,
-KEY_STOP,128,,,0xe068,0xe028,0x0a,243,VK_BROWSER_STOP,0xa9,,,,,BrowserStop,STOP,stop,0x01,
-KEY_AGAIN,129,,,0xe005,,0x0b,121,,,,,,,Again,AGAI,again,0x03,
-KEY_PROPS,130,,,0xe006,,0x0c,,,,,,,,Props,PROP,props,0x19,
-KEY_UNDO,131,,,0xe007,,0x10,122,,,,,,,Undo,UNDO,undo,0x1a,
-KEY_FRONT,132,,,0xe00c,,,119,,,,,,,,FRNT,front,0x31,
-KEY_COPY,133,,,0xe078,,0x18,124,,,,,,,Copy,COPY,copy,0x33,
-KEY_OPEN,134,,,0x64,,0x20,116,,,,,,,Open,OPEN,open,0x48,
-KEY_PASTE,135,,,0x65,,0x28,125,,,,,,,Paste,PAST,paste,0x49,
-KEY_FIND,136,,,0xe041,,0x30,126,,,,,,,Find,FIND,find,0x5f,
-KEY_FIND,136,,,0xe041,,0x30,244,,,,,,,Find,FIND,find,0x5f,
-KEY_CUT,137,,,0xe03c,,0x38,123,,,,,,,Cut,CUT,cut,0x61,
-KEY_HELP,138,Help,0x72,0xe075,,0x09,117,VK_HELP,0x2f,,,XK_Help,0xff6a,Help,HELP,help,0x76,
-KEY_MENU,139,,,0xe01e,,0x91,118,,,,,,,,I147,menu,,
-KEY_CALC,140,,,0xe021,0xe02b,0xa3,251,,,,,,,LaunchApp2,I148,calculator,,
-KEY_SETUP,141,,,0x66,,,,,,,,,,,I149,,,
-KEY_SLEEP,142,,,0xe05f,0xe03f,,248,VK_SLEEP,0x5f,,,,,Sleep,I150,sleep,,
-KEY_WAKEUP,143,,,0xe063,0xe05e,,,,,,,,,WakeUp,I151,wake,,
-KEY_FILE,144,,,0x67,,,,,,,,,,,I152,,,
-KEY_SENDFILE,145,,,0x68,,,,,,,,,,,I153,,,
-KEY_DELETEFILE,146,,,0x69,,,,,,,,,,,I154,,,
-KEY_XFER,147,,,0xe013,,0xa2,,,,,,,,,XFER,,,
-KEY_XFER,147,,,0xe013,,0xa2,,,,,,,,,I155,,,
-KEY_PROG1,148,,,0xe01f,,0xa0,,,,,,,,,I156,,,
-KEY_PROG2,149,,,0xe017,,0xa1,,,,,,,,,I157,,,
-KEY_WWW,150,,,0xe002,,,240,,,,,,,,I158,,,
-KEY_MSDOS,151,,,0x6a,,,,,,,,,,,I159,,,
-KEY_SCREENLOCK,152,,,0xe012,,0x96,249,,,,,,,,I160,,,
-KEY_DIRECTION,153,,,0x6b,,,,,,,,,,,I161,,,
-KEY_CYCLEWINDOWS,154,,,0xe026,,0x9b,,,,,,,,,I162,,,
-KEY_MAIL,155,,,0xe06c,0xe048,,,,,,,,,LaunchMail,I163,mail,,
-KEY_BOOKMARKS,156,,,0xe066,0xe018,,,,,,,,,BrowserFavorites,I164,ac_bookmarks,,
-KEY_COMPUTER,157,,,0xe06b,0xe040,,,,,,,,,LaunchApp1,I165,computer,,
-KEY_BACK,158,,,0xe06a,0xe038,,241,VK_BROWSER_BACK,0xa6,,,,,BrowserBack,I166,ac_back,,
-KEY_FORWARD,159,,,0xe069,0xe030,,242,VK_BROWSER_FORWARD,0xa7,,,,,BrowserForward,I167,ac_forward,,
-KEY_CLOSECD,160,,,0xe023,,0x9a,,,,,,,,,I168,,,
-KEY_EJECTCD,161,,,0x6c,,,236,,,,,,,,I169,,,
-KEY_EJECTCLOSECD,162,,,0xe07d,,,,,,,,,,Eject,I170,,,
-KEY_NEXTSONG,163,,,0xe019,0xe04d,0x93,235,VK_MEDIA_NEXT_TRACK,0xb0,,,,,MediaTrackNext,I171,audionext,,
-KEY_PLAYPAUSE,164,,,0xe022,0xe034,,232,VK_MEDIA_PLAY_PAUSE,0xb3,,,,,MediaPlayPause,I172,audioplay,,
-KEY_PREVIOUSSONG,165,,,0xe010,0xe015,0x94,234,VK_MEDIA_PREV_TRACK,0xb1,,,,,MediaTrackPrevious,I173,audioprev,,
-KEY_STOPCD,166,,,0xe024,0xe03b,0x98,233,VK_MEDIA_STOP,0xb2,,,,,MediaStop,I174,audiostop,,
-KEY_RECORD,167,,,0xe031,,0x9e,,,,,,,,,I175,,,
-KEY_REWIND,168,,,0xe018,,0x9f,,,,,,,,,I176,,,
-KEY_PHONE,169,,,0x63,,,,,,,,,,,I177,,,
-KEY_ISO,170,ISO_Section,0xa,,,,,,,,,,,,I178,,,
-KEY_CONFIG,171,,,0xe001,,,,,,,,,,,I179,,,
-KEY_HOMEPAGE,172,,,0xe032,0xe03a,0x97,,VK_BROWSER_HOME,0xac,,,,,BrowserHome,I180,ac_home,,
-KEY_REFRESH,173,,,0xe067,0xe020,,250,VK_BROWSER_REFRESH,0xa8,,,,,BrowserRefresh,I181,ac_refresh,,
-KEY_EXIT,174,,,,,,,,,,,,,,I182,,,
-KEY_MOVE,175,,,,,,,,,,,,,,I183,,,
-KEY_EDIT,176,,,0xe008,,,247,,,,,,,,I184,,,
-KEY_SCROLLUP,177,,,0x75,,,245,,,,,,,,I185,,,
-KEY_SCROLLDOWN,178,,,0xe00f,,,246,,,,,,,,I186,,,
-KEY_KPLEFTPAREN,179,,,0xe076,,,182,,,,,,,NumpadParenLeft,I187,,,
-KEY_KPRIGHTPAREN,180,,,0xe07b,,,183,,,,,,,NumpadParenRight,I188,,,
-KEY_NEW,181,,,0xe009,,,,,,,,,,,I189,,,
-KEY_REDO,182,,,0xe00a,,,,,,,,,,,I190,,,
-KEY_F13,183,F13,0x69,0x5d,0x2f,0x7f,104,VK_F13,0x7c,0x6e,0x6e,,,F13,FK13,,,0x69
-KEY_F14,184,F14,0x6b,0x5e,0x37,0x80,105,VK_F14,0x7d,0x6f,0x6f,,,F14,FK14,,,0x6b
-KEY_F15,185,F15,0x71,0x5f,0x3f,0x81,106,VK_F15,0x7e,0x70,0x70,,,F15,FK15,,,0x71
-KEY_F16,186,F16,0x6a,0x55,,0x82,107,VK_F16,0x7f,0x71,0x71,,,F16,FK16,,,
-KEY_F17,187,F17,0x40,0xe003,,0x83,108,VK_F17,0x80,0x72,0x72,,,F17,FK17,,,
-KEY_F18,188,F18,0x4f,0xe077,,,109,VK_F18,0x81,,,,,F18,FK18,,,
-KEY_F19,189,F19,0x50,0xe004,,,110,VK_F19,0x82,,,,,F19,FK19,,,
-KEY_F20,190,F20,0x5a,0x5a,,,111,VK_F20,0x83,,,,,F20,FK20,,,
-KEY_F21,191,,,0x74,,,112,VK_F21,0x84,,,,,F21,FK21,,,
-KEY_F22,192,,,0xe079,,,113,VK_F22,0x85,,,,,F22,FK22,,,
-KEY_F23,193,,,0x6d,,,114,VK_F23,0x86,,,,,F23,FK23,,,
-KEY_F24,194,,,0x6f,,,115,VK_F24,0x87,,,,,F24,FK24,,,
-,195,,,0xe015,,,,,,,,,,,,,,
-,196,,,0xe016,,,,,,,,,,,,,,
-,197,,,0xe01a,,,,,,,,,,,,,,
-,198,,,0xe01b,,,,,,,,,,,,,,
-,199,,,0xe027,,,,,,,,,,,,,,
-KEY_PLAYCD,200,,,0xe028,,,,,,,,,,,I208,,,
-KEY_PAUSECD,201,,,0xe029,,,,,,,,,,,I209,,,
-KEY_PROG3,202,,,0xe02b,,,,,,,,,,,I210,,,
-KEY_PROG4,203,,,0xe02c,,,,,,,,,,,I211,,,
-KEY_DASHBOARD,204,,,0xe02d,,,,,,,,,,,I212,,,
-KEY_SUSPEND,205,,,0xe025,,,,,,,,,,Suspend,I213,,,
-KEY_CLOSE,206,,,0xe02f,,,,,,,,,,,I214,,,
-KEY_PLAY,207,,,0xe033,,,,VK_PLAY,0xfa,,,,,,I215,,,
-KEY_FASTFORWARD,208,,,0xe034,,,,,,,,,,,I216,,,
-KEY_BASSBOOST,209,,,0xe036,,,,,,,,,,,I217,,,
-KEY_PRINT,210,,,0xe039,,,,VK_PRINT,0x2a,,,,,,I218,,,
-KEY_HP,211,,,0xe03a,,,,,,,,,,,I219,,,
-KEY_CAMERA,212,,,0xe03b,,,,,,,,,,,I220,,,
-KEY_SOUND,213,,,0xe03d,,,,,,,,,,,I221,,,
-KEY_QUESTION,214,,,0xe03e,,,,,,,,,,,I222,,,
-KEY_EMAIL,215,,,0xe03f,,,,VK_LAUNCH_MAIL,0xb4,,,,,,I223,,,
-KEY_CHAT,216,,,0xe040,,,,,,,,,,,I224,,,
-KEY_SEARCH,217,,,0xe065,0xe010,,,VK_BROWSER_SEARCH,0xaa,,,,,BrowserSearch,I225,,,
-KEY_CONNECT,218,,,0xe042,,,,,,,,,,,I226,,,
-KEY_FINANCE,219,,,0xe043,,,,,,,,,,,I227,,,
-KEY_SPORT,220,,,0xe044,,,,,,,,,,,I228,,,
-KEY_SHOP,221,,,0xe045,,,,,,,,,,,I229,,,
-KEY_ALTERASE,222,,,0xe014,,,,,,,,,,,I230,,,
-KEY_CANCEL,223,,,0xe04a,,,,,,,,,,,I231,,,
-KEY_BRIGHTNESSDOWN,224,,,0xe04c,,,,,,,,,,,I232,,,
-KEY_BRIGHTNESSUP,225,,,0xe054,,,,,,,,,,,I233,,,
-KEY_MEDIA,226,,,0xe06d,0xe050,,,,,,,,,MediaSelect,I234,mediaselect,,
-KEY_SWITCHVIDEOMODE,227,,,0xe056,,,,,,,,,,,I235,,,
-KEY_KBDILLUMTOGGLE,228,,,0xe057,,,,,,,,,,,I236,,,
-KEY_KBDILLUMDOWN,229,,,0xe058,,,,,,,,,,,I237,,,
-KEY_KBDILLUMUP,230,,,0xe059,,,,,,,,,,,I238,,,
-KEY_SEND,231,,,0xe05a,,,,,,,,,,,I239,,,
-KEY_REPLY,232,,,0xe064,,,,,,,,,,,I240,,,
-KEY_FORWARDMAIL,233,,,0xe00e,,,,,,,,,,,I241,,,
-KEY_SAVE,234,,,0xe055,,,,,,,,,,,I242,,,
-KEY_DOCUMENTS,235,,,0xe070,,,,,,,,,,,I243,,,
-KEY_BATTERY,236,,,0xe071,,,,,,,,,,,I244,,,
-KEY_BLUETOOTH,237,,,0xe072,,,,,,,,,,,I245,,,
-KEY_WLAN,238,,,0xe073,,,,,,,,,,,I246,,,
-KEY_UWB,239,,,0xe074,,,,,,,,,,,I247,,,
-KEY_UNKNOWN,240,,,,,,,,,,,,,,I248,,,
-KEY_VIDEO_NEXT,241,,,,,,,,,,,,,,I249,,,
-KEY_VIDEO_PREV,242,,,,,,,,,,,,,,I250,,,
-KEY_BRIGHTNESS_CYCLE,243,,,,,,,,,,,,,,I251,,,
-KEY_BRIGHTNESS_ZERO,244,,,,,,,,,,,,,,I252,,,
-KEY_DISPLAY_OFF,245,,,,,,,,,,,,,,I253,,,
-KEY_WIMAX,246,,,,,,,,,,,,,,,,,
-,247,,,,,,,,,,,,,,,,,
-,248,,,,,,,,,,,,,,,,,
-,249,,,,,,,,,,,,,,,,,
-,250,,,,,,,,,,,,,,,,,
-,251,,,,,,,,,,,,,,,,,
-,252,,,,,,,,,,,,,,,,,
-,253,,,,,,,,,,,,,,,,,
-,254,,,,,,,,,,,,,,,,,
-,255,,,,0xe012,,,,,,,,,,,,,
-BTN_MISC,0x100,,,,,,,,,,,,,,,,,
-BTN_0,0x100,,,,,,,VK_LBUTTON,0x01,,,,,,,,,
-BTN_1,0x101,,,,,,,VK_RBUTTON,0x02,,,,,,,,,
-BTN_2,0x102,,,,,,,VK_MBUTTON,0x04,,,,,,,,,
-BTN_3,0x103,,,,,,,VK_XBUTTON1,0x05,,,,,,,,,
-BTN_4,0x104,,,,,,,VK_XBUTTON2,0x06,,,,,,,,,
-BTN_5,0x105,,,,,,,,,,,,,,,,,
-BTN_6,0x106,,,,,,,,,,,,,,,,,
-BTN_7,0x107,,,,,,,,,,,,,,,,,
-BTN_8,0x108,,,,,,,,,,,,,,,,,
-BTN_9,0x109,,,,,,,,,,,,,,,,,
-BTN_MOUSE,0x110,,,,,,,,,,,,,,,,,
-BTN_LEFT,0x110,,,,,,,,,,,,,,,,,
-BTN_RIGHT,0x111,,,,,,,,,,,,,,,,,
-BTN_MIDDLE,0x112,,,,,,,,,,,,,,,,,
-BTN_SIDE,0x113,,,,,,,,,,,,,,,,,
-BTN_EXTRA,0x114,,,,,,,,,,,,,,,,,
-BTN_FORWARD,0x115,,,,,,,,,,,,,,,,,
-BTN_BACK,0x116,,,,,,,,,,,,,,,,,
-BTN_TASK,0x117,,,,,,,,,,,,,,,,,
-BTN_JOYSTICK,0x120,,,,,,,,,,,,,,,,,
-BTN_TRIGGER,0x120,,,,,,,,,,,,,,,,,
-BTN_THUMB,0x121,,,,,,,,,,,,,,,,,
-BTN_THUMB2,0x122,,,,,,,,,,,,,,,,,
-BTN_TOP,0x123,,,,,,,,,,,,,,,,,
-BTN_TOP2,0x124,,,,,,,,,,,,,,,,,
-BTN_PINKIE,0x125,,,,,,,,,,,,,,,,,
-BTN_BASE,0x126,,,,,,,,,,,,,,,,,
-BTN_BASE2,0x127,,,,,,,,,,,,,,,,,
-BTN_BASE3,0x128,,,,,,,,,,,,,,,,,
-BTN_BASE4,0x129,,,,,,,,,,,,,,,,,
-BTN_BASE5,0x12a,,,,,,,,,,,,,,,,,
-BTN_BASE6,0x12b,,,,,,,,,,,,,,,,,
-BTN_DEAD,0x12f,,,,,,,,,,,,,,,,,
-BTN_GAMEPAD,0x130,,,,,,,,,,,,,,,,,
-BTN_A,0x130,,,,,,,,,,,,,,,,,
-BTN_B,0x131,,,,,,,,,,,,,,,,,
-BTN_C,0x132,,,,,,,,,,,,,,,,,
-BTN_X,0x133,,,,,,,,,,,,,,,,,
-BTN_Y,0x134,,,,,,,,,,,,,,,,,
-BTN_Z,0x135,,,,,,,,,,,,,,,,,
-BTN_TL,0x136,,,,,,,,,,,,,,,,,
-BTN_TR,0x137,,,,,,,,,,,,,,,,,
-BTN_TL2,0x138,,,,,,,,,,,,,,,,,
-BTN_TR2,0x139,,,,,,,,,,,,,,,,,
-BTN_SELECT,0x13a,,,,,,,,,,,,,,,,,
-BTN_START,0x13b,,,,,,,,,,,,,,,,,
-BTN_MODE,0x13c,,,,,,,,,,,,,,,,,
-BTN_THUMBL,0x13d,,,,,,,,,,,,,,,,,
-BTN_THUMBR,0x13e,,,,,,,,,,,,,,,,,
-BTN_DIGI,0x140,,,,,,,,,,,,,,,,,
-BTN_TOOL_PEN,0x140,,,,,,,,,,,,,,,,,
-BTN_TOOL_RUBBER,0x141,,,,,,,,,,,,,,,,,
-BTN_TOOL_BRUSH,0x142,,,,,,,,,,,,,,,,,
-BTN_TOOL_PENCIL,0x143,,,,,,,,,,,,,,,,,
-BTN_TOOL_AIRBRUSH,0x144,,,,,,,,,,,,,,,,,
-BTN_TOOL_FINGER,0x145,,,,,,,,,,,,,,,,,
-BTN_TOOL_MOUSE,0x146,,,,,,,,,,,,,,,,,
-BTN_TOOL_LENS,0x147,,,,,,,,,,,,,,,,,
-BTN_TOUCH,0x14a,,,,,,,,,,,,,,,,,
-BTN_STYLUS,0x14b,,,,,,,,,,,,,,,,,
-BTN_STYLUS2,0x14c,,,,,,,,,,,,,,,,,
-BTN_TOOL_DOUBLETAP,0x14d,,,,,,,,,,,,,,,,,
-BTN_TOOL_TRIPLETAP,0x14e,,,,,,,,,,,,,,,,,
-BTN_TOOL_QUADTAP,0x14f,,,,,,,,,,,,,,,,,
-BTN_WHEEL,0x150,,,,,,,,,,,,,,,,,
-BTN_GEAR_DOWN,0x150,,,,,,,,,,,,,,,,,
-BTN_GEAR_UP,0x151,,,,,,,,,,,,,,,,,
-KEY_OK,0x160,,,,,,,,,,,,,,,,,
-KEY_SELECT,0x161,,,,,,,VK_SELECT,0x29,,,XK_Select,0xff60,Select,SELE,,,
-KEY_GOTO,0x162,,,,,,,,,,,,,,,,,
-KEY_CLEAR,0x163,,,,,,,,,,,,,NumpadClear,CLR,,,
-KEY_POWER2,0x164,,,,,,,,,,,,,,,,,
-KEY_OPTION,0x165,,,,,,,,,,,,,,,,,
-KEY_INFO,0x166,,,,,,,,,,,,,,,,,
-KEY_TIME,0x167,,,,,,,,,,,,,,,,,
-KEY_VENDOR,0x168,,,,,,,,,,,,,,,,,
-KEY_ARCHIVE,0x169,,,,,,,,,,,,,,,,,
-KEY_PROGRAM,0x16a,,,,,,,,,,,,,,,,,
-KEY_CHANNEL,0x16b,,,,,,,,,,,,,,,,,
-KEY_FAVORITES,0x16c,,,,,,,VK_BROWSER_FAVOURITES,0xab,,,,,,,,,
-KEY_EPG,0x16d,,,,,,,,,,,,,,,,,
-KEY_PVR,0x16e,,,,,,,,,,,,,,,,,
-KEY_MHP,0x16f,,,,,,,,,,,,,,,,,
-KEY_LANGUAGE,0x170,,,,,,,,,,,,,,,,,
-KEY_TITLE,0x171,,,,,,,,,,,,,,,,,
-KEY_SUBTITLE,0x172,,,,,,,,,,,,,,,,,
-KEY_ANGLE,0x173,,,,,,,,,,,,,,,,,
-KEY_ZOOM,0x174,,,,,,,VK_ZOOM,0xfb,,,,,,,,,
-KEY_MODE,0x175,,,,,,,,,,,,,,,,,
-KEY_KEYBOARD,0x176,,,,,,,,,,,,,,,,,
-KEY_SCREEN,0x177,,,,,,,,,,,,,,,,,
-KEY_PC,0x178,,,,,,,,,,,,,,,,,
-KEY_TV,0x179,,,,,,,,,,,,,,,,,
-KEY_TV2,0x17a,,,,,,,,,,,,,,,,,
-KEY_VCR,0x17b,,,,,,,,,,,,,,,,,
-KEY_VCR2,0x17c,,,,,,,,,,,,,,,,,
-KEY_SAT,0x17d,,,,,,,,,,,,,,,,,
-KEY_SAT2,0x17e,,,,,,,,,,,,,,,,,
-KEY_CD,0x17f,,,,,,,,,,,,,,,,,
-KEY_TAPE,0x180,,,,,,,,,,,,,,,,,
-KEY_RADIO,0x181,,,,,,,,,,,,,,,,,
-KEY_TUNER,0x182,,,,,,,,,,,,,,,,,
-KEY_PLAYER,0x183,,,,,,,,,,,,,,,,,
-KEY_TEXT,0x184,,,,,,,,,,,,,,,,,
-KEY_DVD,0x185,,,,,,,,,,,,,,,,,
-KEY_AUX,0x186,,,,,,,,,,,,,,,,,
-KEY_MP3,0x187,,,,,,,,,,,,,,,,,
-KEY_AUDIO,0x188,,,,,,,,,,,,,,,,,
-KEY_VIDEO,0x189,,,,,,,,,,,,,,,,,
-KEY_DIRECTORY,0x18a,,,,,,,,,,,,,,,,,
-KEY_LIST,0x18b,,,,,,,,,,,,,,,,,
-KEY_MEMO,0x18c,,,,,,,,,,,,,,,,,
-KEY_CALENDAR,0x18d,,,,,,,,,,,,,,,,,
-KEY_RED,0x18e,,,,,,,,,,,,,,,,,
-KEY_GREEN,0x18f,,,,,,,,,,,,,,,,,
-KEY_YELLOW,0x190,,,,,,,,,,,,,,,,,
-KEY_BLUE,0x191,,,,,,,,,,,,,,,,,
-KEY_CHANNELUP,0x192,,,,,,,,,,,,,,,,,
-KEY_CHANNELDOWN,0x193,,,,,,,,,,,,,,,,,
-KEY_FIRST,0x194,,,,,,,,,,,,,,,,,
-KEY_LAST,0x195,,,,,,,,,,,,,,,,,
-KEY_AB,0x196,,,,,,,,,,,,,,,,,
-KEY_NEXT,0x197,,,,,,,,,,,,,,,,,
-KEY_RESTART,0x198,,,,,,,,,,,,,,,,,
-KEY_SLOW,0x199,,,,,,,,,,,,,,,,,
-KEY_SHUFFLE,0x19a,,,,,,,,,,,,,,,,,
-KEY_BREAK,0x19b,,,,,,,,,,,,,,BREA,,,
-KEY_BREAK,0x19b,,,,,,,,,,,,,,BRK,,,
-KEY_PREVIOUS,0x19c,,,,,,,,,,,,,,,,,
-KEY_DIGITS,0x19d,,,,,,,,,,,,,,,,,
-KEY_TEEN,0x19e,,,,,,,,,,,,,,,,,
-KEY_TWEN,0x19f,,,,,,,,,,,,,,,,,
-KEY_VIDEOPHONE,0x1a0,,,,,,,,,,,,,,,,,
-KEY_GAMES,0x1a1,,,,,,,,,,,,,,,,,
-KEY_ZOOMIN,0x1a2,,,,,,,,,,,,,,,,,
-KEY_ZOOMOUT,0x1a3,,,,,,,,,,,,,,,,,
-KEY_ZOOMRESET,0x1a4,,,,,,,,,,,,,,,,,
-KEY_WORDPROCESSOR,0x1a5,,,,,,,,,,,,,,,,,
-KEY_EDITOR,0x1a6,,,,,,,,,,,,,,,,,
-KEY_SPREADSHEET,0x1a7,,,,,,,,,,,,,,,,,
-KEY_GRAPHICSEDITOR,0x1a8,,,,,,,,,,,,,,,,,
-KEY_PRESENTATION,0x1a9,,,,,,,,,,,,,,,,,
-KEY_DATABASE,0x1aa,,,,,,,,,,,,,,,,,
-KEY_NEWS,0x1ab,,,,,,,,,,,,,,,,,
-KEY_VOICEMAIL,0x1ac,,,,,,,,,,,,,,,,,
-KEY_ADDRESSBOOK,0x1ad,,,,,,,,,,,,,,,,,
-KEY_MESSENGER,0x1ae,,,,,,,,,,,,,,,,,
-KEY_DISPLAYTOGGLE,0x1af,,,,,,,,,,,,,,,,,
-KEY_SPELLCHECK,0x1b0,,,,,,,,,,,,,,,,,
-KEY_LOGOFF,0x1b1,,,,,,,,,,,,,,,,,
-KEY_DOLLAR,0x1b2,,,,,,,,,,,,,,,,,
-KEY_EURO,0x1b3,,,,,,,,,,,,,,,,,
-KEY_FRAMEBACK,0x1b4,,,,,,,,,,,,,,,,,
-KEY_FRAMEFORWARD,0x1b5,,,,,,,,,,,,,,,,,
-KEY_CONTEXT_MENU,0x1b6,,,,,,,,,,,,,,,,,
-KEY_MEDIA_REPEAT,0x1b7,,,,,,,,,,,,,,,,,
-KEY_DEL_EOL,0x1c0,,,,,,,,,,,,,,,,,
-KEY_DEL_EOS,0x1c1,,,,,,,,,,,,,,,,,
-KEY_INS_LINE,0x1c2,,,,,,,,,,,,,,,,,
-KEY_DEL_LINE,0x1c3,,,,,,,,,,,,,,,,,
-KEY_FN,0x1d0,Function,0x3f,,,,,,,,,,,Fn,,,,
-KEY_FN_ESC,0x1d1,,,,,,,,,,,,,,,,,
-KEY_FN_F1,0x1d2,,,,,,,,,,,,,,,,,
-KEY_FN_F2,0x1d3,,,,,,,,,,,,,,,,,
-KEY_FN_F3,0x1d4,,,,,,,,,,,,,,,,,
-KEY_FN_F4,0x1d5,,,,,,,,,,,,,,,,,
-KEY_FN_F5,0x1d6,,,,,,,,,,,,,,,,,
-KEY_FN_F6,0x1d7,,,,,,,,,,,,,,,,,
-KEY_FN_F7,0x1d8,,,,,,,,,,,,,,,,,
-KEY_FN_F8,0x1d9,,,,,,,,,,,,,,,,,
-KEY_FN_F9,0x1da,,,,,,,,,,,,,,,,,
-KEY_FN_F10,0x1db,,,,,,,,,,,,,,,,,
-KEY_FN_F11,0x1dc,,,,,,,,,,,,,,,,,
-KEY_FN_F12,0x1dd,,,,,,,,,,,,,,,,,
-KEY_FN_1,0x1de,,,,,,,,,,,,,,,,,
-KEY_FN_2,0x1df,,,,,,,,,,,,,,,,,
-KEY_FN_D,0x1e0,,,,,,,,,,,,,,,,,
-KEY_FN_E,0x1e1,,,,,,,,,,,,,,,,,
-KEY_FN_F,0x1e2,,,,,,,,,,,,,,,,,
-KEY_FN_S,0x1e3,,,,,,,,,,,,,,,,,
-KEY_FN_B,0x1e4,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT1,0x1f1,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT2,0x1f2,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT3,0x1f3,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT4,0x1f4,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT5,0x1f5,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT6,0x1f6,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT7,0x1f7,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT8,0x1f8,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT9,0x1f9,,,,,,,,,,,,,,,,,
-KEY_BRL_DOT10,0x1fa,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_0,0x200,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_1,0x201,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_2,0x202,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_3,0x203,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_4,0x204,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_5,0x205,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_6,0x206,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_7,0x207,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_8,0x208,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_9,0x209,,,,,,,,,,,,,,,,,
-KEY_NUMERIC_STAR,0x20a,,,,,,,,,,,,,NumpadStar,,,,
-KEY_NUMERIC_POUND,0x20b,,,,,,,,,,,,,NumpadHash,,,,
-KEY_RFKILL,0x20c,,,,,,,,,,,,,,,,,
diff --git a/keycodemapdb/meson.build b/keycodemapdb/meson.build
deleted file mode 100644
index eb9416b..0000000
--- a/keycodemapdb/meson.build
+++ /dev/null
@@ -1 +0,0 @@
-project('keycodemapdb')
diff --git a/keycodemapdb/tests/.gitignore b/keycodemapdb/tests/.gitignore
deleted file mode 100644
index 0562305..0000000
--- a/keycodemapdb/tests/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-osx2win32.*
-osx2win32_name.*
-osx2xkb.*
-osx2xkb_name.*
-html2win32.*
-html2win32_name.*
-osx.*
-osx_name.*
-stdc
-stdc++
-node_modules/
diff --git a/keycodemapdb/tests/Makefile b/keycodemapdb/tests/Makefile
deleted file mode 100644
index e1b3875..0000000
--- a/keycodemapdb/tests/Makefile
+++ /dev/null
@@ -1,150 +0,0 @@
-TESTS := stdc stdc++ python2 python3 javascript
-
-check: $(TESTS)
-	@set -e; for fn in $(TESTS); do \
-		./$$fn; \
-		echo $$fn: OK; \
-	done
-	@echo Done.
-
-GEN := ../tools/keymap-gen
-DATA := ../data/keymaps.csv
-SOURCES := $(GEN) $(DATA)
-
-.DELETE_ON_ERROR:
-
-stdc: stdc.c osx2win32.h osx2win32.c osx2win32_name.h osx2win32_name.c \
-             osx2xkb.h osx2xkb.c osx2xkb_name.h osx2xkb_name.c \
-             html2win32.h html2win32.c html2win32_name.h html2win32_name.c \
-             osx.h osx.c osx_name.h osx_name.c
-	$(CC) -Wall -o $@ $(filter %.c, $^)
-osx2win32.c: $(SOURCES)
-	$(GEN) --lang stdc code-map $(DATA) osx win32 > $@
-osx2win32.h: $(SOURCES)
-	$(GEN) --lang stdc-header code-map $(DATA) osx win32 > $@
-osx2win32_name.c: $(SOURCES)
-	$(GEN) --lang stdc name-map $(DATA) osx win32 > $@
-osx2win32_name.h: $(SOURCES)
-	$(GEN) --lang stdc-header name-map $(DATA) osx win32 > $@
-osx2xkb.c: $(SOURCES)
-	$(GEN) --lang stdc code-map $(DATA) osx xkb > $@
-osx2xkb.h: $(SOURCES)
-	$(GEN) --lang stdc-header code-map $(DATA) osx xkb > $@
-osx2xkb_name.c: $(SOURCES)
-	$(GEN) --lang stdc name-map $(DATA) osx xkb > $@
-osx2xkb_name.h: $(SOURCES)
-	$(GEN) --lang stdc-header name-map $(DATA) osx xkb > $@
-html2win32.c: $(SOURCES)
-	$(GEN) --lang stdc code-map $(DATA) html win32 > $@
-html2win32.h: $(SOURCES)
-	$(GEN) --lang stdc-header code-map $(DATA) html win32 > $@
-html2win32_name.c: $(SOURCES)
-	$(GEN) --lang stdc name-map $(DATA) html win32 > $@
-html2win32_name.h: $(SOURCES)
-	$(GEN) --lang stdc-header name-map $(DATA) html win32 > $@
-osx.c: $(SOURCES)
-	$(GEN) --lang stdc code-table $(DATA) osx > $@
-osx.h: $(SOURCES)
-	$(GEN) --lang stdc-header code-table $(DATA) osx > $@
-osx_name.c: $(SOURCES)
-	$(GEN) --lang stdc name-table $(DATA) osx > $@
-osx_name.h: $(SOURCES)
-	$(GEN) --lang stdc-header name-table $(DATA) osx > $@
-
-stdc++: stdc++.cc osx2win32.hh osx2win32.cc osx2win32_name.hh osx2win32_name.cc \
-             osx2xkb.hh osx2xkb.cc osx2xkb_name.hh osx2xkb_name.cc \
-             html2win32.hh html2win32.cc html2win32_name.hh html2win32_name.cc \
-             osx.hh osx.cc osx_name.hh osx_name.cc
-	$(CXX) -Wall -std=c++11 -o $@ $(filter %.cc, $^)
-osx2win32.cc: $(SOURCES)
-	$(GEN) --lang stdc++ code-map $(DATA) osx win32 > $@
-osx2win32.hh: $(SOURCES)
-	$(GEN) --lang stdc++-header code-map $(DATA) osx win32 > $@
-osx2win32_name.cc: $(SOURCES)
-	$(GEN) --lang stdc++ name-map $(DATA) osx win32 > $@
-osx2win32_name.hh: $(SOURCES)
-	$(GEN) --lang stdc++-header name-map $(DATA) osx win32 > $@
-osx2xkb.cc: $(SOURCES)
-	$(GEN) --lang stdc++ code-map $(DATA) osx xkb > $@
-osx2xkb.hh: $(SOURCES)
-	$(GEN) --lang stdc++-header code-map $(DATA) osx xkb > $@
-osx2xkb_name.cc: $(SOURCES)
-	$(GEN) --lang stdc++ name-map $(DATA) osx xkb > $@
-osx2xkb_name.hh: $(SOURCES)
-	$(GEN) --lang stdc++-header name-map $(DATA) osx xkb > $@
-html2win32.cc: $(SOURCES)
-	$(GEN) --lang stdc++ code-map $(DATA) html win32 > $@
-html2win32.hh: $(SOURCES)
-	$(GEN) --lang stdc++-header code-map $(DATA) html win32 > $@
-html2win32_name.cc: $(SOURCES)
-	$(GEN) --lang stdc++ name-map $(DATA) html win32 > $@
-html2win32_name.hh: $(SOURCES)
-	$(GEN) --lang stdc++-header name-map $(DATA) html win32 > $@
-osx.cc: $(SOURCES)
-	$(GEN) --lang stdc++ code-table $(DATA) osx > $@
-osx.hh: $(SOURCES)
-	$(GEN) --lang stdc++-header code-table $(DATA) osx > $@
-osx_name.cc: $(SOURCES)
-	$(GEN) --lang stdc++ name-table $(DATA) osx > $@
-osx_name.hh: $(SOURCES)
-	$(GEN) --lang stdc++-header name-table $(DATA) osx > $@
-
-python2: osx2win32.py osx2win32_name.py \
-         osx2xkb.py osx2xkb_name.py \
-         html2win32.py html2win32_name.py \
-         osx.py osx_name.py
-osx2win32.py: $(SOURCES)
-	$(GEN) --lang python2 code-map $(DATA) osx win32 > $@
-osx2win32_name.py: $(SOURCES)
-	$(GEN) --lang python2 name-map $(DATA) osx win32 > $@
-osx2xkb.py: $(SOURCES)
-	$(GEN) --lang python2 code-map $(DATA) osx xkb > $@
-osx2xkb_name.py: $(SOURCES)
-	$(GEN) --lang python2 name-map $(DATA) osx xkb > $@
-html2win32.py: $(SOURCES)
-	$(GEN) --lang python2 code-map $(DATA) html win32 > $@
-html2win32_name.py: $(SOURCES)
-	$(GEN) --lang python2 name-map $(DATA) html win32 > $@
-osx.py: $(SOURCES)
-	$(GEN) --lang python2 code-table $(DATA) osx > $@
-osx_name.py: $(SOURCES)
-	$(GEN) --lang python2 name-table $(DATA) osx > $@
-
-javascript: node_modules/babel-core \
-            node_modules/babel-plugin-transform-es2015-modules-commonjs \
-            osx2win32.js osx2win32_name.js \
-            osx2xkb.js osx2xkb_name.js \
-            html2win32.js html2win32_name.js \
-            osx.js osx_name.js
-node_modules/babel-core:
-	npm install babel-core
-node_modules/babel-plugin-transform-es2015-modules-commonjs:
-	npm install babel-plugin-transform-es2015-modules-commonjs
-osx2win32.js: $(SOURCES)
-	$(GEN) --lang js code-map $(DATA) osx win32 > $@
-osx2win32_name.js: $(SOURCES)
-	$(GEN) --lang js name-map $(DATA) osx win32 > $@
-osx2xkb.js: $(SOURCES)
-	$(GEN) --lang js code-map $(DATA) osx xkb > $@
-osx2xkb_name.js: $(SOURCES)
-	$(GEN) --lang js name-map $(DATA) osx xkb > $@
-html2win32.js: $(SOURCES)
-	$(GEN) --lang js code-map $(DATA) html win32 > $@
-html2win32_name.js: $(SOURCES)
-	$(GEN) --lang js name-map $(DATA) html win32 > $@
-osx.js: $(SOURCES)
-	$(GEN) --lang js code-table $(DATA) osx > $@
-osx_name.js: $(SOURCES)
-	$(GEN) --lang js name-table $(DATA) osx > $@
-
-clean:
-	rm -rf node_modules
-	rm -f osx2win32.*
-	rm -f osx2win32_name.*
-	rm -f osx2xkb.*
-	rm -f osx2xkb_name.*
-	rm -f html2win32.*
-	rm -f html2win32_name.*
-	rm -f osx.*
-	rm -f osx_name.*
-	rm -f stdc stdc++
diff --git a/keycodemapdb/tests/javascript b/keycodemapdb/tests/javascript
deleted file mode 100755
index 5179db2..0000000
--- a/keycodemapdb/tests/javascript
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env node
-/*
- * Keycode Map Generator JavaScript Tests
- *
- * Copyright 2017 Pierre Ossman for Cendio AB
- *
- * This file is dual license under the terms of the GPLv2 or later
- * and 3-clause BSD licenses.
- */
-
-"use strict";
-
-var assert = require('assert');
-var babel = require('babel-core');
-var fs = require('fs');
-
-function include(fn) {
-  var options = {
-    plugins: ["transform-es2015-modules-commonjs"]
-  };
-
-  var code = babel.transformFileSync(fn, options).code;
-  fs.writeFileSync("." + fn + "_nodejs.js", code);
-  var imp = require("./." + fn + "_nodejs.js");
-  fs.unlinkSync("./." + fn + "_nodejs.js");
-
-  return imp
-}
-
-var code_map_osx_to_win32 = include("osx2win32.js").default;
-var name_map_osx_to_win32 = include("osx2win32_name.js").default;
-
-var code_map_osx_to_xkb = include("osx2xkb.js").default;
-var name_map_osx_to_xkb = include("osx2xkb_name.js").default;
-
-var code_map_html_to_win32 = include("html2win32.js").default;
-var name_map_html_to_win32 = include("html2win32_name.js").default;
-
-var code_table_osx = include("osx.js").default;
-var name_table_osx = include("osx_name.js").default;
-
-assert.equal(code_map_osx_to_win32[0x1d], 0x30);
-assert.equal(name_map_osx_to_win32[0x1d], "VK_0");
-
-assert.equal(code_map_osx_to_xkb[0x1d], "AE10");
-assert.equal(name_map_osx_to_xkb[0x1d], "AE10");
-
-assert.equal(code_map_html_to_win32["ControlLeft"], 0x11);
-assert.equal(name_map_html_to_win32["ControlLeft"], "VK_CONTROL");
-
-assert.equal(code_table_osx[0x1d], 0x3b);
-assert.equal(name_table_osx[0x1d], "Control");
-
diff --git a/keycodemapdb/tests/python2 b/keycodemapdb/tests/python2
deleted file mode 100755
index 28a5b03..0000000
--- a/keycodemapdb/tests/python2
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-python ./test.py
diff --git a/keycodemapdb/tests/python3 b/keycodemapdb/tests/python3
deleted file mode 100755
index ded1f68..0000000
--- a/keycodemapdb/tests/python3
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-python3 ./test.py
diff --git a/keycodemapdb/tests/stdc++.cc b/keycodemapdb/tests/stdc++.cc
deleted file mode 100644
index 5e3e8f5..0000000
--- a/keycodemapdb/tests/stdc++.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Keycode Map Generator C++ Tests
- *
- * Copyright 2017 Pierre Ossman for Cendio AB
- *
- * This file is dual license under the terms of the GPLv2 or later
- * and 3-clause BSD licenses.
- */
-
-#include <assert.h>
-#include <string.h>
-
-#include "osx2win32.hh"
-#include "osx2win32_name.hh"
-
-#include "osx2xkb.hh"
-#include "osx2xkb_name.hh"
-
-#include "html2win32.hh"
-#include "html2win32_name.hh"
-
-#include "osx.hh"
-#include "osx_name.hh"
-
-int main(int argc, char** argv)
-{
-	assert(code_map_osx_to_win32[0x1d] == 0x30);
-	assert(strcmp(name_map_osx_to_win32[0x1d], "VK_0") == 0);
-
-	assert(strcmp(code_map_osx_to_xkb[0x1d], "AE10") == 0);
-	assert(strcmp(name_map_osx_to_xkb[0x1d], "AE10") == 0);
-
-	assert(code_map_html_to_win32.at("ControlLeft") == 0x11);
-	assert(strcmp(name_map_html_to_win32.at("ControlLeft"), "VK_CONTROL") == 0);
-
-	assert(code_table_osx[0x1d] == 0x3b);
-	assert(strcmp(name_table_osx[0x1d], "Control") == 0);
-
-	return 0;
-}
diff --git a/keycodemapdb/tests/stdc.c b/keycodemapdb/tests/stdc.c
deleted file mode 100644
index e4946fa..0000000
--- a/keycodemapdb/tests/stdc.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Keycode Map Generator C Tests
- *
- * Copyright 2017 Pierre Ossman for Cendio AB
- *
- * This file is dual license under the terms of the GPLv2 or later
- * and 3-clause BSD licenses.
- */
-
-#include <assert.h>
-#include <string.h>
-
-#include "osx2win32.h"
-#include "osx2win32_name.h"
-
-#include "osx2xkb.h"
-#include "osx2xkb_name.h"
-
-#include "html2win32.h"
-#include "html2win32_name.h"
-
-#include "osx.h"
-#include "osx_name.h"
-
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
-
-int main(int argc, char** argv)
-{
-	unsigned i;
-
-	assert(code_map_osx_to_win32_len == ARRAY_SIZE(code_map_osx_to_win32));
-	assert(code_map_osx_to_win32[0x1d] == 0x30);
-	assert(name_map_osx_to_win32_len == ARRAY_SIZE(name_map_osx_to_win32));
-	assert(strcmp(name_map_osx_to_win32[0x1d], "VK_0") == 0);
-
-	assert(code_map_osx_to_xkb_len == ARRAY_SIZE(code_map_osx_to_xkb));
-	assert(strcmp(code_map_osx_to_xkb[0x1d], "AE10") == 0);
-	assert(name_map_osx_to_xkb_len == ARRAY_SIZE(name_map_osx_to_xkb));
-	assert(strcmp(name_map_osx_to_xkb[0x1d], "AE10") == 0);
-
-	assert(code_map_html_to_win32_len == ARRAY_SIZE(code_map_html_to_win32));
-	for (i = 0;i < code_map_html_to_win32_len;i++) {
-		if (strcmp(code_map_html_to_win32[i].from, "ControlLeft") == 0) {
-			assert(code_map_html_to_win32[i].to == 0x11);
-			break;
-		}
-	}
-	assert(i != code_map_html_to_win32_len);
-	assert(name_map_html_to_win32_len == ARRAY_SIZE(name_map_html_to_win32));
-	for (i = 0;i < name_map_html_to_win32_len;i++) {
-		if (strcmp(name_map_html_to_win32[i].from, "ControlLeft") == 0) {
-			assert(strcmp(name_map_html_to_win32[i].to, "VK_CONTROL") == 0);
-			break;
-		}
-	}
-	assert(i != name_map_html_to_win32_len);
-
-	assert(code_table_osx_len == ARRAY_SIZE(code_table_osx));
-	assert(code_table_osx[0x1d] == 0x3b);
-	assert(name_table_osx_len == ARRAY_SIZE(name_table_osx));
-	assert(strcmp(name_table_osx[0x1d], "Control") == 0);
-
-	return 0;
-}
diff --git a/keycodemapdb/tests/test.py b/keycodemapdb/tests/test.py
deleted file mode 100644
index f265145..0000000
--- a/keycodemapdb/tests/test.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Keycode Map Generator Python Tests
-#
-# Copyright 2017 Pierre Ossman for Cendio AB
-#
-# This file is dual license under the terms of the GPLv2 or later
-# and 3-clause BSD licenses.
-
-import osx2win32
-import osx2win32_name
-
-import osx2xkb
-import osx2xkb_name
-
-import html2win32
-import html2win32_name
-
-import osx
-import osx_name
-
-assert osx2win32.code_map_osx_to_win32[0x1d] == 0x30
-assert osx2win32_name.name_map_osx_to_win32[0x1d] == "VK_0"
-
-assert osx2xkb.code_map_osx_to_xkb[0x1d] == "AE10"
-assert osx2xkb_name.name_map_osx_to_xkb[0x1d] == "AE10"
-
-assert html2win32.code_map_html_to_win32["ControlLeft"] == 0x11
-assert html2win32_name.name_map_html_to_win32["ControlLeft"] == "VK_CONTROL"
-
-assert osx.code_table_osx[0x1d] == 0x3b;
-assert osx_name.name_table_osx[0x1d] == "Control";
diff --git a/keycodemapdb/thirdparty/LICENSE-argparse.txt b/keycodemapdb/thirdparty/LICENSE-argparse.txt
deleted file mode 100644
index 640bc78..0000000
--- a/keycodemapdb/thirdparty/LICENSE-argparse.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-argparse is (c) 2006-2009 Steven J. Bethard <steven.bethard at gmail.com>.
-
-The argparse module was contributed to Python as of Python 2.7 and thus
-was licensed under the Python license. Same license applies to all files in
-the argparse package project.
-
-For details about the Python License, please see doc/Python-License.txt.
-
-History
--------
-
-Before (and including) argparse 1.1, the argparse package was licensed under
-Apache License v2.0.
-
-After argparse 1.1, all project files from the argparse project were deleted
-due to license compatibility issues between Apache License 2.0 and GNU GPL v2.
-
-The project repository then had a clean start with some files taken from
-Python 2.7.1, so definitely all files are under Python License now.
-
diff --git a/keycodemapdb/thirdparty/__init__.py b/keycodemapdb/thirdparty/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/keycodemapdb/thirdparty/argparse.py b/keycodemapdb/thirdparty/argparse.py
deleted file mode 100644
index 70a77cc..0000000
--- a/keycodemapdb/thirdparty/argparse.py
+++ /dev/null
@@ -1,2392 +0,0 @@
-# Author: Steven J. Bethard <steven.bethard at gmail.com>.
-# Maintainer: Thomas Waldmann <tw at waldmann-edv.de>
-
-"""Command-line parsing library
-
-This module is an optparse-inspired command-line parsing library that:
-
-    - handles both optional and positional arguments
-    - produces highly informative usage messages
-    - supports parsers that dispatch to sub-parsers
-
-The following is a simple usage example that sums integers from the
-command-line and writes the result to a file::
-
-    parser = argparse.ArgumentParser(
-        description='sum the integers at the command line')
-    parser.add_argument(
-        'integers', metavar='int', nargs='+', type=int,
-        help='an integer to be summed')
-    parser.add_argument(
-        '--log', default=sys.stdout, type=argparse.FileType('w'),
-        help='the file where the sum should be written')
-    args = parser.parse_args()
-    args.log.write('%s' % sum(args.integers))
-    args.log.close()
-
-The module contains the following public classes:
-
-    - ArgumentParser -- The main entry point for command-line parsing. As the
-        example above shows, the add_argument() method is used to populate
-        the parser with actions for optional and positional arguments. Then
-        the parse_args() method is invoked to convert the args at the
-        command-line into an object with attributes.
-
-    - ArgumentError -- The exception raised by ArgumentParser objects when
-        there are errors with the parser's actions. Errors raised while
-        parsing the command-line are caught by ArgumentParser and emitted
-        as command-line messages.
-
-    - FileType -- A factory for defining types of files to be created. As the
-        example above shows, instances of FileType are typically passed as
-        the type= argument of add_argument() calls.
-
-    - Action -- The base class for parser actions. Typically actions are
-        selected by passing strings like 'store_true' or 'append_const' to
-        the action= argument of add_argument(). However, for greater
-        customization of ArgumentParser actions, subclasses of Action may
-        be defined and passed as the action= argument.
-
-    - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
-        ArgumentDefaultsHelpFormatter -- Formatter classes which
-        may be passed as the formatter_class= argument to the
-        ArgumentParser constructor. HelpFormatter is the default,
-        RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
-        not to change the formatting for help text, and
-        ArgumentDefaultsHelpFormatter adds information about argument defaults
-        to the help.
-
-All other classes in this module are considered implementation details.
-(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
-considered public as object names -- the API of the formatter objects is
-still considered an implementation detail.)
-"""
-
-__version__ = '1.4.0'  # we use our own version number independant of the
-                       # one in stdlib and we release this on pypi.
-
-__external_lib__ = True  # to make sure the tests really test THIS lib,
-                         # not the builtin one in Python stdlib
-
-__all__ = [
-    'ArgumentParser',
-    'ArgumentError',
-    'ArgumentTypeError',
-    'FileType',
-    'HelpFormatter',
-    'ArgumentDefaultsHelpFormatter',
-    'RawDescriptionHelpFormatter',
-    'RawTextHelpFormatter',
-    'Namespace',
-    'Action',
-    'ONE_OR_MORE',
-    'OPTIONAL',
-    'PARSER',
-    'REMAINDER',
-    'SUPPRESS',
-    'ZERO_OR_MORE',
-]
-
-
-import copy as _copy
-import os as _os
-import re as _re
-import sys as _sys
-import textwrap as _textwrap
-
-from gettext import gettext as _
-
-try:
-    set
-except NameError:
-    # for python < 2.4 compatibility (sets module is there since 2.3):
-    from sets import Set as set
-
-try:
-    basestring
-except NameError:
-    basestring = str
-
-try:
-    sorted
-except NameError:
-    # for python < 2.4 compatibility:
-    def sorted(iterable, reverse=False):
-        result = list(iterable)
-        result.sort()
-        if reverse:
-            result.reverse()
-        return result
-
-
-def _callable(obj):
-    return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
-
-
-SUPPRESS = '==SUPPRESS=='
-
-OPTIONAL = '?'
-ZERO_OR_MORE = '*'
-ONE_OR_MORE = '+'
-PARSER = 'A...'
-REMAINDER = '...'
-_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'
-
-# =============================
-# Utility functions and classes
-# =============================
-
-class _AttributeHolder(object):
-    """Abstract base class that provides __repr__.
-
-    The __repr__ method returns a string in the format::
-        ClassName(attr=name, attr=name, ...)
-    The attributes are determined either by a class-level attribute,
-    '_kwarg_names', or by inspecting the instance __dict__.
-    """
-
-    def __repr__(self):
-        type_name = type(self).__name__
-        arg_strings = []
-        for arg in self._get_args():
-            arg_strings.append(repr(arg))
-        for name, value in self._get_kwargs():
-            arg_strings.append('%s=%r' % (name, value))
-        return '%s(%s)' % (type_name, ', '.join(arg_strings))
-
-    def _get_kwargs(self):
-        return sorted(self.__dict__.items())
-
-    def _get_args(self):
-        return []
-
-
-def _ensure_value(namespace, name, value):
-    if getattr(namespace, name, None) is None:
-        setattr(namespace, name, value)
-    return getattr(namespace, name)
-
-
-# ===============
-# Formatting Help
-# ===============
-
-class HelpFormatter(object):
-    """Formatter for generating usage messages and argument help strings.
-
-    Only the name of this class is considered a public API. All the methods
-    provided by the class are considered an implementation detail.
-    """
-
-    def __init__(self,
-                 prog,
-                 indent_increment=2,
-                 max_help_position=24,
-                 width=None):
-
-        # default setting for width
-        if width is None:
-            try:
-                width = int(_os.environ['COLUMNS'])
-            except (KeyError, ValueError):
-                width = 80
-            width -= 2
-
-        self._prog = prog
-        self._indent_increment = indent_increment
-        self._max_help_position = max_help_position
-        self._width = width
-
-        self._current_indent = 0
-        self._level = 0
-        self._action_max_length = 0
-
-        self._root_section = self._Section(self, None)
-        self._current_section = self._root_section
-
-        self._whitespace_matcher = _re.compile(r'\s+')
-        self._long_break_matcher = _re.compile(r'\n\n\n+')
-
-    # ===============================
-    # Section and indentation methods
-    # ===============================
-    def _indent(self):
-        self._current_indent += self._indent_increment
-        self._level += 1
-
-    def _dedent(self):
-        self._current_indent -= self._indent_increment
-        assert self._current_indent >= 0, 'Indent decreased below 0.'
-        self._level -= 1
-
-    class _Section(object):
-
-        def __init__(self, formatter, parent, heading=None):
-            self.formatter = formatter
-            self.parent = parent
-            self.heading = heading
-            self.items = []
-
-        def format_help(self):
-            # format the indented section
-            if self.parent is not None:
-                self.formatter._indent()
-            join = self.formatter._join_parts
-            for func, args in self.items:
-                func(*args)
-            item_help = join([func(*args) for func, args in self.items])
-            if self.parent is not None:
-                self.formatter._dedent()
-
-            # return nothing if the section was empty
-            if not item_help:
-                return ''
-
-            # add the heading if the section was non-empty
-            if self.heading is not SUPPRESS and self.heading is not None:
-                current_indent = self.formatter._current_indent
-                heading = '%*s%s:\n' % (current_indent, '', self.heading)
-            else:
-                heading = ''
-
-            # join the section-initial newline, the heading and the help
-            return join(['\n', heading, item_help, '\n'])
-
-    def _add_item(self, func, args):
-        self._current_section.items.append((func, args))
-
-    # ========================
-    # Message building methods
-    # ========================
-    def start_section(self, heading):
-        self._indent()
-        section = self._Section(self, self._current_section, heading)
-        self._add_item(section.format_help, [])
-        self._current_section = section
-
-    def end_section(self):
-        self._current_section = self._current_section.parent
-        self._dedent()
-
-    def add_text(self, text):
-        if text is not SUPPRESS and text is not None:
-            self._add_item(self._format_text, [text])
-
-    def add_usage(self, usage, actions, groups, prefix=None):
-        if usage is not SUPPRESS:
-            args = usage, actions, groups, prefix
-            self._add_item(self._format_usage, args)
-
-    def add_argument(self, action):
-        if action.help is not SUPPRESS:
-
-            # find all invocations
-            get_invocation = self._format_action_invocation
-            invocations = [get_invocation(action)]
-            for subaction in self._iter_indented_subactions(action):
-                invocations.append(get_invocation(subaction))
-
-            # update the maximum item length
-            invocation_length = max([len(s) for s in invocations])
-            action_length = invocation_length + self._current_indent
-            self._action_max_length = max(self._action_max_length,
-                                          action_length)
-
-            # add the item to the list
-            self._add_item(self._format_action, [action])
-
-    def add_arguments(self, actions):
-        for action in actions:
-            self.add_argument(action)
-
-    # =======================
-    # Help-formatting methods
-    # =======================
-    def format_help(self):
-        help = self._root_section.format_help()
-        if help:
-            help = self._long_break_matcher.sub('\n\n', help)
-            help = help.strip('\n') + '\n'
-        return help
-
-    def _join_parts(self, part_strings):
-        return ''.join([part
-                        for part in part_strings
-                        if part and part is not SUPPRESS])
-
-    def _format_usage(self, usage, actions, groups, prefix):
-        if prefix is None:
-            prefix = _('usage: ')
-
-        # if usage is specified, use that
-        if usage is not None:
-            usage = usage % dict(prog=self._prog)
-
-        # if no optionals or positionals are available, usage is just prog
-        elif usage is None and not actions:
-            usage = '%(prog)s' % dict(prog=self._prog)
-
-        # if optionals and positionals are available, calculate usage
-        elif usage is None:
-            prog = '%(prog)s' % dict(prog=self._prog)
-
-            # split optionals from positionals
-            optionals = []
-            positionals = []
-            for action in actions:
-                if action.option_strings:
-                    optionals.append(action)
-                else:
-                    positionals.append(action)
-
-            # build full usage string
-            format = self._format_actions_usage
-            action_usage = format(optionals + positionals, groups)
-            usage = ' '.join([s for s in [prog, action_usage] if s])
-
-            # wrap the usage parts if it's too long
-            text_width = self._width - self._current_indent
-            if len(prefix) + len(usage) > text_width:
-
-                # break usage into wrappable parts
-                part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
-                opt_usage = format(optionals, groups)
-                pos_usage = format(positionals, groups)
-                opt_parts = _re.findall(part_regexp, opt_usage)
-                pos_parts = _re.findall(part_regexp, pos_usage)
-                assert ' '.join(opt_parts) == opt_usage
-                assert ' '.join(pos_parts) == pos_usage
-
-                # helper for wrapping lines
-                def get_lines(parts, indent, prefix=None):
-                    lines = []
-                    line = []
-                    if prefix is not None:
-                        line_len = len(prefix) - 1
-                    else:
-                        line_len = len(indent) - 1
-                    for part in parts:
-                        if line_len + 1 + len(part) > text_width:
-                            lines.append(indent + ' '.join(line))
-                            line = []
-                            line_len = len(indent) - 1
-                        line.append(part)
-                        line_len += len(part) + 1
-                    if line:
-                        lines.append(indent + ' '.join(line))
-                    if prefix is not None:
-                        lines[0] = lines[0][len(indent):]
-                    return lines
-
-                # if prog is short, follow it with optionals or positionals
-                if len(prefix) + len(prog) <= 0.75 * text_width:
-                    indent = ' ' * (len(prefix) + len(prog) + 1)
-                    if opt_parts:
-                        lines = get_lines([prog] + opt_parts, indent, prefix)
-                        lines.extend(get_lines(pos_parts, indent))
-                    elif pos_parts:
-                        lines = get_lines([prog] + pos_parts, indent, prefix)
-                    else:
-                        lines = [prog]
-
-                # if prog is long, put it on its own line
-                else:
-                    indent = ' ' * len(prefix)
-                    parts = opt_parts + pos_parts
-                    lines = get_lines(parts, indent)
-                    if len(lines) > 1:
-                        lines = []
-                        lines.extend(get_lines(opt_parts, indent))
-                        lines.extend(get_lines(pos_parts, indent))
-                    lines = [prog] + lines
-
-                # join lines into usage
-                usage = '\n'.join(lines)
-
-        # prefix with 'usage:'
-        return '%s%s\n\n' % (prefix, usage)
-
-    def _format_actions_usage(self, actions, groups):
-        # find group indices and identify actions in groups
-        group_actions = set()
-        inserts = {}
-        for group in groups:
-            try:
-                start = actions.index(group._group_actions[0])
-            except ValueError:
-                continue
-            else:
-                end = start + len(group._group_actions)
-                if actions[start:end] == group._group_actions:
-                    for action in group._group_actions:
-                        group_actions.add(action)
-                    if not group.required:
-                        if start in inserts:
-                            inserts[start] += ' ['
-                        else:
-                            inserts[start] = '['
-                        inserts[end] = ']'
-                    else:
-                        if start in inserts:
-                            inserts[start] += ' ('
-                        else:
-                            inserts[start] = '('
-                        inserts[end] = ')'
-                    for i in range(start + 1, end):
-                        inserts[i] = '|'
-
-        # collect all actions format strings
-        parts = []
-        for i, action in enumerate(actions):
-
-            # suppressed arguments are marked with None
-            # remove | separators for suppressed arguments
-            if action.help is SUPPRESS:
-                parts.append(None)
-                if inserts.get(i) == '|':
-                    inserts.pop(i)
-                elif inserts.get(i + 1) == '|':
-                    inserts.pop(i + 1)
-
-            # produce all arg strings
-            elif not action.option_strings:
-                part = self._format_args(action, action.dest)
-
-                # if it's in a group, strip the outer []
-                if action in group_actions:
-                    if part[0] == '[' and part[-1] == ']':
-                        part = part[1:-1]
-
-                # add the action string to the list
-                parts.append(part)
-
-            # produce the first way to invoke the option in brackets
-            else:
-                option_string = action.option_strings[0]
-
-                # if the Optional doesn't take a value, format is:
-                #    -s or --long
-                if action.nargs == 0:
-                    part = '%s' % option_string
-
-                # if the Optional takes a value, format is:
-                #    -s ARGS or --long ARGS
-                else:
-                    default = action.dest.upper()
-                    args_string = self._format_args(action, default)
-                    part = '%s %s' % (option_string, args_string)
-
-                # make it look optional if it's not required or in a group
-                if not action.required and action not in group_actions:
-                    part = '[%s]' % part
-
-                # add the action string to the list
-                parts.append(part)
-
-        # insert things at the necessary indices
-        for i in sorted(inserts, reverse=True):
-            parts[i:i] = [inserts[i]]
-
-        # join all the action items with spaces
-        text = ' '.join([item for item in parts if item is not None])
-
-        # clean up separators for mutually exclusive groups
-        open = r'[\[(]'
-        close = r'[\])]'
-        text = _re.sub(r'(%s) ' % open, r'\1', text)
-        text = _re.sub(r' (%s)' % close, r'\1', text)
-        text = _re.sub(r'%s *%s' % (open, close), r'', text)
-        text = _re.sub(r'\(([^|]*)\)', r'\1', text)
-        text = text.strip()
-
-        # return the text
-        return text
-
-    def _format_text(self, text):
-        if '%(prog)' in text:
-            text = text % dict(prog=self._prog)
-        text_width = self._width - self._current_indent
-        indent = ' ' * self._current_indent
-        return self._fill_text(text, text_width, indent) + '\n\n'
-
-    def _format_action(self, action):
-        # determine the required width and the entry label
-        help_position = min(self._action_max_length + 2,
-                            self._max_help_position)
-        help_width = self._width - help_position
-        action_width = help_position - self._current_indent - 2
-        action_header = self._format_action_invocation(action)
-
-        # ho nelp; start on same line and add a final newline
-        if not action.help:
-            tup = self._current_indent, '', action_header
-            action_header = '%*s%s\n' % tup
-
-        # short action name; start on the same line and pad two spaces
-        elif len(action_header) <= action_width:
-            tup = self._current_indent, '', action_width, action_header
-            action_header = '%*s%-*s  ' % tup
-            indent_first = 0
-
-        # long action name; start on the next line
-        else:
-            tup = self._current_indent, '', action_header
-            action_header = '%*s%s\n' % tup
-            indent_first = help_position
-
-        # collect the pieces of the action help
-        parts = [action_header]
-
-        # if there was help for the action, add lines of help text
-        if action.help:
-            help_text = self._expand_help(action)
-            help_lines = self._split_lines(help_text, help_width)
-            parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
-            for line in help_lines[1:]:
-                parts.append('%*s%s\n' % (help_position, '', line))
-
-        # or add a newline if the description doesn't end with one
-        elif not action_header.endswith('\n'):
-            parts.append('\n')
-
-        # if there are any sub-actions, add their help as well
-        for subaction in self._iter_indented_subactions(action):
-            parts.append(self._format_action(subaction))
-
-        # return a single string
-        return self._join_parts(parts)
-
-    def _format_action_invocation(self, action):
-        if not action.option_strings:
-            metavar, = self._metavar_formatter(action, action.dest)(1)
-            return metavar
-
-        else:
-            parts = []
-
-            # if the Optional doesn't take a value, format is:
-            #    -s, --long
-            if action.nargs == 0:
-                parts.extend(action.option_strings)
-
-            # if the Optional takes a value, format is:
-            #    -s ARGS, --long ARGS
-            else:
-                default = action.dest.upper()
-                args_string = self._format_args(action, default)
-                for option_string in action.option_strings:
-                    parts.append('%s %s' % (option_string, args_string))
-
-            return ', '.join(parts)
-
-    def _metavar_formatter(self, action, default_metavar):
-        if action.metavar is not None:
-            result = action.metavar
-        elif action.choices is not None:
-            choice_strs = [str(choice) for choice in action.choices]
-            result = '{%s}' % ','.join(choice_strs)
-        else:
-            result = default_metavar
-
-        def format(tuple_size):
-            if isinstance(result, tuple):
-                return result
-            else:
-                return (result, ) * tuple_size
-        return format
-
-    def _format_args(self, action, default_metavar):
-        get_metavar = self._metavar_formatter(action, default_metavar)
-        if action.nargs is None:
-            result = '%s' % get_metavar(1)
-        elif action.nargs == OPTIONAL:
-            result = '[%s]' % get_metavar(1)
-        elif action.nargs == ZERO_OR_MORE:
-            result = '[%s [%s ...]]' % get_metavar(2)
-        elif action.nargs == ONE_OR_MORE:
-            result = '%s [%s ...]' % get_metavar(2)
-        elif action.nargs == REMAINDER:
-            result = '...'
-        elif action.nargs == PARSER:
-            result = '%s ...' % get_metavar(1)
-        else:
-            formats = ['%s' for _ in range(action.nargs)]
-            result = ' '.join(formats) % get_metavar(action.nargs)
-        return result
-
-    def _expand_help(self, action):
-        params = dict(vars(action), prog=self._prog)
-        for name in list(params):
-            if params[name] is SUPPRESS:
-                del params[name]
-        for name in list(params):
-            if hasattr(params[name], '__name__'):
-                params[name] = params[name].__name__
-        if params.get('choices') is not None:
-            choices_str = ', '.join([str(c) for c in params['choices']])
-            params['choices'] = choices_str
-        return self._get_help_string(action) % params
-
-    def _iter_indented_subactions(self, action):
-        try:
-            get_subactions = action._get_subactions
-        except AttributeError:
-            pass
-        else:
-            self._indent()
-            for subaction in get_subactions():
-                yield subaction
-            self._dedent()
-
-    def _split_lines(self, text, width):
-        text = self._whitespace_matcher.sub(' ', text).strip()
-        return _textwrap.wrap(text, width)
-
-    def _fill_text(self, text, width, indent):
-        text = self._whitespace_matcher.sub(' ', text).strip()
-        return _textwrap.fill(text, width, initial_indent=indent,
-                                           subsequent_indent=indent)
-
-    def _get_help_string(self, action):
-        return action.help
-
-
-class RawDescriptionHelpFormatter(HelpFormatter):
-    """Help message formatter which retains any formatting in descriptions.
-
-    Only the name of this class is considered a public API. All the methods
-    provided by the class are considered an implementation detail.
-    """
-
-    def _fill_text(self, text, width, indent):
-        return ''.join([indent + line for line in text.splitlines(True)])
-
-
-class RawTextHelpFormatter(RawDescriptionHelpFormatter):
-    """Help message formatter which retains formatting of all help text.
-
-    Only the name of this class is considered a public API. All the methods
-    provided by the class are considered an implementation detail.
-    """
-
-    def _split_lines(self, text, width):
-        return text.splitlines()
-
-
-class ArgumentDefaultsHelpFormatter(HelpFormatter):
-    """Help message formatter which adds default values to argument help.
-
-    Only the name of this class is considered a public API. All the methods
-    provided by the class are considered an implementation detail.
-    """
-
-    def _get_help_string(self, action):
-        help = action.help
-        if '%(default)' not in action.help:
-            if action.default is not SUPPRESS:
-                defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
-                if action.option_strings or action.nargs in defaulting_nargs:
-                    help += ' (default: %(default)s)'
-        return help
-
-
-# =====================
-# Options and Arguments
-# =====================
-
-def _get_action_name(argument):
-    if argument is None:
-        return None
-    elif argument.option_strings:
-        return  '/'.join(argument.option_strings)
-    elif argument.metavar not in (None, SUPPRESS):
-        return argument.metavar
-    elif argument.dest not in (None, SUPPRESS):
-        return argument.dest
-    else:
-        return None
-
-
-class ArgumentError(Exception):
-    """An error from creating or using an argument (optional or positional).
-
-    The string value of this exception is the message, augmented with
-    information about the argument that caused it.
-    """
-
-    def __init__(self, argument, message):
-        self.argument_name = _get_action_name(argument)
-        self.message = message
-
-    def __str__(self):
-        if self.argument_name is None:
-            format = '%(message)s'
-        else:
-            format = 'argument %(argument_name)s: %(message)s'
-        return format % dict(message=self.message,
-                             argument_name=self.argument_name)
-
-
-class ArgumentTypeError(Exception):
-    """An error from trying to convert a command line string to a type."""
-    pass
-
-
-# ==============
-# Action classes
-# ==============
-
-class Action(_AttributeHolder):
-    """Information about how to convert command line strings to Python objects.
-
-    Action objects are used by an ArgumentParser to represent the information
-    needed to parse a single argument from one or more strings from the
-    command line. The keyword arguments to the Action constructor are also
-    all attributes of Action instances.
-
-    Keyword Arguments:
-
-        - option_strings -- A list of command-line option strings which
-            should be associated with this action.
-
-        - dest -- The name of the attribute to hold the created object(s)
-
-        - nargs -- The number of command-line arguments that should be
-            consumed. By default, one argument will be consumed and a single
-            value will be produced.  Other values include:
-                - N (an integer) consumes N arguments (and produces a list)
-                - '?' consumes zero or one arguments
-                - '*' consumes zero or more arguments (and produces a list)
-                - '+' consumes one or more arguments (and produces a list)
-            Note that the difference between the default and nargs=1 is that
-            with the default, a single value will be produced, while with
-            nargs=1, a list containing a single value will be produced.
-
-        - const -- The value to be produced if the option is specified and the
-            option uses an action that takes no values.
-
-        - default -- The value to be produced if the option is not specified.
-
-        - type -- The type which the command-line arguments should be converted
-            to, should be one of 'string', 'int', 'float', 'complex' or a
-            callable object that accepts a single string argument. If None,
-            'string' is assumed.
-
-        - choices -- A container of values that should be allowed. If not None,
-            after a command-line argument has been converted to the appropriate
-            type, an exception will be raised if it is not a member of this
-            collection.
-
-        - required -- True if the action must always be specified at the
-            command line. This is only meaningful for optional command-line
-            arguments.
-
-        - help -- The help string describing the argument.
-
-        - metavar -- The name to be used for the option's argument with the
-            help string. If None, the 'dest' value will be used as the name.
-    """
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 nargs=None,
-                 const=None,
-                 default=None,
-                 type=None,
-                 choices=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        self.option_strings = option_strings
-        self.dest = dest
-        self.nargs = nargs
-        self.const = const
-        self.default = default
-        self.type = type
-        self.choices = choices
-        self.required = required
-        self.help = help
-        self.metavar = metavar
-
-    def _get_kwargs(self):
-        names = [
-            'option_strings',
-            'dest',
-            'nargs',
-            'const',
-            'default',
-            'type',
-            'choices',
-            'help',
-            'metavar',
-        ]
-        return [(name, getattr(self, name)) for name in names]
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        raise NotImplementedError(_('.__call__() not defined'))
-
-
-class _StoreAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 nargs=None,
-                 const=None,
-                 default=None,
-                 type=None,
-                 choices=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        if nargs == 0:
-            raise ValueError('nargs for store actions must be > 0; if you '
-                             'have nothing to store, actions such as store '
-                             'true or store const may be more appropriate')
-        if const is not None and nargs != OPTIONAL:
-            raise ValueError('nargs must be %r to supply const' % OPTIONAL)
-        super(_StoreAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=nargs,
-            const=const,
-            default=default,
-            type=type,
-            choices=choices,
-            required=required,
-            help=help,
-            metavar=metavar)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        setattr(namespace, self.dest, values)
-
-
-class _StoreConstAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 const,
-                 default=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        super(_StoreConstAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=0,
-            const=const,
-            default=default,
-            required=required,
-            help=help)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        setattr(namespace, self.dest, self.const)
-
-
-class _StoreTrueAction(_StoreConstAction):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 default=False,
-                 required=False,
-                 help=None):
-        super(_StoreTrueAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            const=True,
-            default=default,
-            required=required,
-            help=help)
-
-
-class _StoreFalseAction(_StoreConstAction):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 default=True,
-                 required=False,
-                 help=None):
-        super(_StoreFalseAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            const=False,
-            default=default,
-            required=required,
-            help=help)
-
-
-class _AppendAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 nargs=None,
-                 const=None,
-                 default=None,
-                 type=None,
-                 choices=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        if nargs == 0:
-            raise ValueError('nargs for append actions must be > 0; if arg '
-                             'strings are not supplying the value to append, '
-                             'the append const action may be more appropriate')
-        if const is not None and nargs != OPTIONAL:
-            raise ValueError('nargs must be %r to supply const' % OPTIONAL)
-        super(_AppendAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=nargs,
-            const=const,
-            default=default,
-            type=type,
-            choices=choices,
-            required=required,
-            help=help,
-            metavar=metavar)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        items = _copy.copy(_ensure_value(namespace, self.dest, []))
-        items.append(values)
-        setattr(namespace, self.dest, items)
-
-
-class _AppendConstAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 const,
-                 default=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        super(_AppendConstAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=0,
-            const=const,
-            default=default,
-            required=required,
-            help=help,
-            metavar=metavar)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        items = _copy.copy(_ensure_value(namespace, self.dest, []))
-        items.append(self.const)
-        setattr(namespace, self.dest, items)
-
-
-class _CountAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 default=None,
-                 required=False,
-                 help=None):
-        super(_CountAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=0,
-            default=default,
-            required=required,
-            help=help)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        new_count = _ensure_value(namespace, self.dest, 0) + 1
-        setattr(namespace, self.dest, new_count)
-
-
-class _HelpAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest=SUPPRESS,
-                 default=SUPPRESS,
-                 help=None):
-        super(_HelpAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            default=default,
-            nargs=0,
-            help=help)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        parser.print_help()
-        parser.exit()
-
-
-class _VersionAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 version=None,
-                 dest=SUPPRESS,
-                 default=SUPPRESS,
-                 help="show program's version number and exit"):
-        super(_VersionAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            default=default,
-            nargs=0,
-            help=help)
-        self.version = version
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        version = self.version
-        if version is None:
-            version = parser.version
-        formatter = parser._get_formatter()
-        formatter.add_text(version)
-        parser.exit(message=formatter.format_help())
-
-
-class _SubParsersAction(Action):
-
-    class _ChoicesPseudoAction(Action):
-
-        def __init__(self, name, aliases, help):
-            metavar = dest = name
-            if aliases:
-                metavar += ' (%s)' % ', '.join(aliases)
-            sup = super(_SubParsersAction._ChoicesPseudoAction, self)
-            sup.__init__(option_strings=[], dest=dest, help=help,
-                        metavar=metavar)
-
-    def __init__(self,
-                 option_strings,
-                 prog,
-                 parser_class,
-                 dest=SUPPRESS,
-                 help=None,
-                 metavar=None):
-
-        self._prog_prefix = prog
-        self._parser_class = parser_class
-        self._name_parser_map = {}
-        self._choices_actions = []
-
-        super(_SubParsersAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=PARSER,
-            choices=self._name_parser_map,
-            help=help,
-            metavar=metavar)
-
-    def add_parser(self, name, **kwargs):
-        # set prog from the existing prefix
-        if kwargs.get('prog') is None:
-            kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
-
-        aliases = kwargs.pop('aliases', ())
-
-        # create a pseudo-action to hold the choice help
-        if 'help' in kwargs:
-            help = kwargs.pop('help')
-            choice_action = self._ChoicesPseudoAction(name, aliases, help)
-            self._choices_actions.append(choice_action)
-
-        # create the parser and add it to the map
-        parser = self._parser_class(**kwargs)
-        self._name_parser_map[name] = parser
-
-        # make parser available under aliases also
-        for alias in aliases:
-            self._name_parser_map[alias] = parser
-
-        return parser
-
-    def _get_subactions(self):
-        return self._choices_actions
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        parser_name = values[0]
-        arg_strings = values[1:]
-
-        # set the parser name if requested
-        if self.dest is not SUPPRESS:
-            setattr(namespace, self.dest, parser_name)
-
-        # select the parser
-        try:
-            parser = self._name_parser_map[parser_name]
-        except KeyError:
-            tup = parser_name, ', '.join(self._name_parser_map)
-            msg = _('unknown parser %r (choices: %s)' % tup)
-            raise ArgumentError(self, msg)
-
-        # parse all the remaining options into the namespace
-        # store any unrecognized options on the object, so that the top
-        # level parser can decide what to do with them
-        namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)
-        if arg_strings:
-            vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
-            getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
-
-
-# ==============
-# Type classes
-# ==============
-
-class FileType(object):
-    """Factory for creating file object types
-
-    Instances of FileType are typically passed as type= arguments to the
-    ArgumentParser add_argument() method.
-
-    Keyword Arguments:
-        - mode -- A string indicating how the file is to be opened. Accepts the
-            same values as the builtin open() function.
-        - bufsize -- The file's desired buffer size. Accepts the same values as
-            the builtin open() function.
-    """
-
-    def __init__(self, mode='r', bufsize=None):
-        self._mode = mode
-        self._bufsize = bufsize
-
-    def __call__(self, string):
-        # the special argument "-" means sys.std{in,out}
-        if string == '-':
-            if 'r' in self._mode:
-                return _sys.stdin
-            elif 'w' in self._mode:
-                return _sys.stdout
-            else:
-                msg = _('argument "-" with mode %r' % self._mode)
-                raise ValueError(msg)
-
-        try:
-            # all other arguments are used as file names
-            if self._bufsize:
-                return open(string, self._mode, self._bufsize)
-            else:
-                return open(string, self._mode)
-        except IOError:
-            err = _sys.exc_info()[1]
-            message = _("can't open '%s': %s")
-            raise ArgumentTypeError(message % (string, err))
-
-    def __repr__(self):
-        args = [self._mode, self._bufsize]
-        args_str = ', '.join([repr(arg) for arg in args if arg is not None])
-        return '%s(%s)' % (type(self).__name__, args_str)
-
-# ===========================
-# Optional and Positional Parsing
-# ===========================
-
-class Namespace(_AttributeHolder):
-    """Simple object for storing attributes.
-
-    Implements equality by attribute names and values, and provides a simple
-    string representation.
-    """
-
-    def __init__(self, **kwargs):
-        for name in kwargs:
-            setattr(self, name, kwargs[name])
-
-    __hash__ = None
-
-    def __eq__(self, other):
-        return vars(self) == vars(other)
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __contains__(self, key):
-        return key in self.__dict__
-
-
-class _ActionsContainer(object):
-
-    def __init__(self,
-                 description,
-                 prefix_chars,
-                 argument_default,
-                 conflict_handler):
-        super(_ActionsContainer, self).__init__()
-
-        self.description = description
-        self.argument_default = argument_default
-        self.prefix_chars = prefix_chars
-        self.conflict_handler = conflict_handler
-
-        # set up registries
-        self._registries = {}
-
-        # register actions
-        self.register('action', None, _StoreAction)
-        self.register('action', 'store', _StoreAction)
-        self.register('action', 'store_const', _StoreConstAction)
-        self.register('action', 'store_true', _StoreTrueAction)
-        self.register('action', 'store_false', _StoreFalseAction)
-        self.register('action', 'append', _AppendAction)
-        self.register('action', 'append_const', _AppendConstAction)
-        self.register('action', 'count', _CountAction)
-        self.register('action', 'help', _HelpAction)
-        self.register('action', 'version', _VersionAction)
-        self.register('action', 'parsers', _SubParsersAction)
-
-        # raise an exception if the conflict handler is invalid
-        self._get_handler()
-
-        # action storage
-        self._actions = []
-        self._option_string_actions = {}
-
-        # groups
-        self._action_groups = []
-        self._mutually_exclusive_groups = []
-
-        # defaults storage
-        self._defaults = {}
-
-        # determines whether an "option" looks like a negative number
-        self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')
-
-        # whether or not there are any optionals that look like negative
-        # numbers -- uses a list so it can be shared and edited
-        self._has_negative_number_optionals = []
-
-    # ====================
-    # Registration methods
-    # ====================
-    def register(self, registry_name, value, object):
-        registry = self._registries.setdefault(registry_name, {})
-        registry[value] = object
-
-    def _registry_get(self, registry_name, value, default=None):
-        return self._registries[registry_name].get(value, default)
-
-    # ==================================
-    # Namespace default accessor methods
-    # ==================================
-    def set_defaults(self, **kwargs):
-        self._defaults.update(kwargs)
-
-        # if these defaults match any existing arguments, replace
-        # the previous default on the object with the new one
-        for action in self._actions:
-            if action.dest in kwargs:
-                action.default = kwargs[action.dest]
-
-    def get_default(self, dest):
-        for action in self._actions:
-            if action.dest == dest and action.default is not None:
-                return action.default
-        return self._defaults.get(dest, None)
-
-
-    # =======================
-    # Adding argument actions
-    # =======================
-    def add_argument(self, *args, **kwargs):
-        """
-        add_argument(dest, ..., name=value, ...)
-        add_argument(option_string, option_string, ..., name=value, ...)
-        """
-
-        # if no positional args are supplied or only one is supplied and
-        # it doesn't look like an option string, parse a positional
-        # argument
-        chars = self.prefix_chars
-        if not args or len(args) == 1 and args[0][0] not in chars:
-            if args and 'dest' in kwargs:
-                raise ValueError('dest supplied twice for positional argument')
-            kwargs = self._get_positional_kwargs(*args, **kwargs)
-
-        # otherwise, we're adding an optional argument
-        else:
-            kwargs = self._get_optional_kwargs(*args, **kwargs)
-
-        # if no default was supplied, use the parser-level default
-        if 'default' not in kwargs:
-            dest = kwargs['dest']
-            if dest in self._defaults:
-                kwargs['default'] = self._defaults[dest]
-            elif self.argument_default is not None:
-                kwargs['default'] = self.argument_default
-
-        # create the action object, and add it to the parser
-        action_class = self._pop_action_class(kwargs)
-        if not _callable(action_class):
-            raise ValueError('unknown action "%s"' % action_class)
-        action = action_class(**kwargs)
-
-        # raise an error if the action type is not callable
-        type_func = self._registry_get('type', action.type, action.type)
-        if not _callable(type_func):
-            raise ValueError('%r is not callable' % type_func)
-
-        return self._add_action(action)
-
-    def add_argument_group(self, *args, **kwargs):
-        group = _ArgumentGroup(self, *args, **kwargs)
-        self._action_groups.append(group)
-        return group
-
-    def add_mutually_exclusive_group(self, **kwargs):
-        group = _MutuallyExclusiveGroup(self, **kwargs)
-        self._mutually_exclusive_groups.append(group)
-        return group
-
-    def _add_action(self, action):
-        # resolve any conflicts
-        self._check_conflict(action)
-
-        # add to actions list
-        self._actions.append(action)
-        action.container = self
-
-        # index the action by any option strings it has
-        for option_string in action.option_strings:
-            self._option_string_actions[option_string] = action
-
-        # set the flag if any option strings look like negative numbers
-        for option_string in action.option_strings:
-            if self._negative_number_matcher.match(option_string):
-                if not self._has_negative_number_optionals:
-                    self._has_negative_number_optionals.append(True)
-
-        # return the created action
-        return action
-
-    def _remove_action(self, action):
-        self._actions.remove(action)
-
-    def _add_container_actions(self, container):
-        # collect groups by titles
-        title_group_map = {}
-        for group in self._action_groups:
-            if group.title in title_group_map:
-                msg = _('cannot merge actions - two groups are named %r')
-                raise ValueError(msg % (group.title))
-            title_group_map[group.title] = group
-
-        # map each action to its group
-        group_map = {}
-        for group in container._action_groups:
-
-            # if a group with the title exists, use that, otherwise
-            # create a new group matching the container's group
-            if group.title not in title_group_map:
-                title_group_map[group.title] = self.add_argument_group(
-                    title=group.title,
-                    description=group.description,
-                    conflict_handler=group.conflict_handler)
-
-            # map the actions to their new group
-            for action in group._group_actions:
-                group_map[action] = title_group_map[group.title]
-
-        # add container's mutually exclusive groups
-        # NOTE: if add_mutually_exclusive_group ever gains title= and
-        # description= then this code will need to be expanded as above
-        for group in container._mutually_exclusive_groups:
-            mutex_group = self.add_mutually_exclusive_group(
-                required=group.required)
-
-            # map the actions to their new mutex group
-            for action in group._group_actions:
-                group_map[action] = mutex_group
-
-        # add all actions to this container or their group
-        for action in container._actions:
-            group_map.get(action, self)._add_action(action)
-
-    def _get_positional_kwargs(self, dest, **kwargs):
-        # make sure required is not specified
-        if 'required' in kwargs:
-            msg = _("'required' is an invalid argument for positionals")
-            raise TypeError(msg)
-
-        # mark positional arguments as required if at least one is
-        # always required
-        if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
-            kwargs['required'] = True
-        if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
-            kwargs['required'] = True
-
-        # return the keyword arguments with no option strings
-        return dict(kwargs, dest=dest, option_strings=[])
-
-    def _get_optional_kwargs(self, *args, **kwargs):
-        # determine short and long option strings
-        option_strings = []
-        long_option_strings = []
-        for option_string in args:
-            # error on strings that don't start with an appropriate prefix
-            if not option_string[0] in self.prefix_chars:
-                msg = _('invalid option string %r: '
-                        'must start with a character %r')
-                tup = option_string, self.prefix_chars
-                raise ValueError(msg % tup)
-
-            # strings starting with two prefix characters are long options
-            option_strings.append(option_string)
-            if option_string[0] in self.prefix_chars:
-                if len(option_string) > 1:
-                    if option_string[1] in self.prefix_chars:
-                        long_option_strings.append(option_string)
-
-        # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
-        dest = kwargs.pop('dest', None)
-        if dest is None:
-            if long_option_strings:
-                dest_option_string = long_option_strings[0]
-            else:
-                dest_option_string = option_strings[0]
-            dest = dest_option_string.lstrip(self.prefix_chars)
-            if not dest:
-                msg = _('dest= is required for options like %r')
-                raise ValueError(msg % option_string)
-            dest = dest.replace('-', '_')
-
-        # return the updated keyword arguments
-        return dict(kwargs, dest=dest, option_strings=option_strings)
-
-    def _pop_action_class(self, kwargs, default=None):
-        action = kwargs.pop('action', default)
-        return self._registry_get('action', action, action)
-
-    def _get_handler(self):
-        # determine function from conflict handler string
-        handler_func_name = '_handle_conflict_%s' % self.conflict_handler
-        try:
-            return getattr(self, handler_func_name)
-        except AttributeError:
-            msg = _('invalid conflict_resolution value: %r')
-            raise ValueError(msg % self.conflict_handler)
-
-    def _check_conflict(self, action):
-
-        # find all options that conflict with this option
-        confl_optionals = []
-        for option_string in action.option_strings:
-            if option_string in self._option_string_actions:
-                confl_optional = self._option_string_actions[option_string]
-                confl_optionals.append((option_string, confl_optional))
-
-        # resolve any conflicts
-        if confl_optionals:
-            conflict_handler = self._get_handler()
-            conflict_handler(action, confl_optionals)
-
-    def _handle_conflict_error(self, action, conflicting_actions):
-        message = _('conflicting option string(s): %s')
-        conflict_string = ', '.join([option_string
-                                     for option_string, action
-                                     in conflicting_actions])
-        raise ArgumentError(action, message % conflict_string)
-
-    def _handle_conflict_resolve(self, action, conflicting_actions):
-
-        # remove all conflicting options
-        for option_string, action in conflicting_actions:
-
-            # remove the conflicting option
-            action.option_strings.remove(option_string)
-            self._option_string_actions.pop(option_string, None)
-
-            # if the option now has no option string, remove it from the
-            # container holding it
-            if not action.option_strings:
-                action.container._remove_action(action)
-
-
-class _ArgumentGroup(_ActionsContainer):
-
-    def __init__(self, container, title=None, description=None, **kwargs):
-        # add any missing keyword arguments by checking the container
-        update = kwargs.setdefault
-        update('conflict_handler', container.conflict_handler)
-        update('prefix_chars', container.prefix_chars)
-        update('argument_default', container.argument_default)
-        super_init = super(_ArgumentGroup, self).__init__
-        super_init(description=description, **kwargs)
-
-        # group attributes
-        self.title = title
-        self._group_actions = []
-
-        # share most attributes with the container
-        self._registries = container._registries
-        self._actions = container._actions
-        self._option_string_actions = container._option_string_actions
-        self._defaults = container._defaults
-        self._has_negative_number_optionals = \
-            container._has_negative_number_optionals
-
-    def _add_action(self, action):
-        action = super(_ArgumentGroup, self)._add_action(action)
-        self._group_actions.append(action)
-        return action
-
-    def _remove_action(self, action):
-        super(_ArgumentGroup, self)._remove_action(action)
-        self._group_actions.remove(action)
-
-
-class _MutuallyExclusiveGroup(_ArgumentGroup):
-
-    def __init__(self, container, required=False):
-        super(_MutuallyExclusiveGroup, self).__init__(container)
-        self.required = required
-        self._container = container
-
-    def _add_action(self, action):
-        if action.required:
-            msg = _('mutually exclusive arguments must be optional')
-            raise ValueError(msg)
-        action = self._container._add_action(action)
-        self._group_actions.append(action)
-        return action
-
-    def _remove_action(self, action):
-        self._container._remove_action(action)
-        self._group_actions.remove(action)
-
-
-class ArgumentParser(_AttributeHolder, _ActionsContainer):
-    """Object for parsing command line strings into Python objects.
-
-    Keyword Arguments:
-        - prog -- The name of the program (default: sys.argv[0])
-        - usage -- A usage message (default: auto-generated from arguments)
-        - description -- A description of what the program does
-        - epilog -- Text following the argument descriptions
-        - parents -- Parsers whose arguments should be copied into this one
-        - formatter_class -- HelpFormatter class for printing help messages
-        - prefix_chars -- Characters that prefix optional arguments
-        - fromfile_prefix_chars -- Characters that prefix files containing
-            additional arguments
-        - argument_default -- The default value for all arguments
-        - conflict_handler -- String indicating how to handle conflicts
-        - add_help -- Add a -h/-help option
-    """
-
-    def __init__(self,
-                 prog=None,
-                 usage=None,
-                 description=None,
-                 epilog=None,
-                 version=None,
-                 parents=[],
-                 formatter_class=HelpFormatter,
-                 prefix_chars='-',
-                 fromfile_prefix_chars=None,
-                 argument_default=None,
-                 conflict_handler='error',
-                 add_help=True):
-
-        if version is not None:
-            import warnings
-            warnings.warn(
-                """The "version" argument to ArgumentParser is deprecated. """
-                """Please use """
-                """"add_argument(..., action='version', version="N", ...)" """
-                """instead""", DeprecationWarning)
-
-        superinit = super(ArgumentParser, self).__init__
-        superinit(description=description,
-                  prefix_chars=prefix_chars,
-                  argument_default=argument_default,
-                  conflict_handler=conflict_handler)
-
-        # default setting for prog
-        if prog is None:
-            prog = _os.path.basename(_sys.argv[0])
-
-        self.prog = prog
-        self.usage = usage
-        self.epilog = epilog
-        self.version = version
-        self.formatter_class = formatter_class
-        self.fromfile_prefix_chars = fromfile_prefix_chars
-        self.add_help = add_help
-
-        add_group = self.add_argument_group
-        self._positionals = add_group(_('positional arguments'))
-        self._optionals = add_group(_('optional arguments'))
-        self._subparsers = None
-
-        # register types
-        def identity(string):
-            return string
-        self.register('type', None, identity)
-
-        # add help and version arguments if necessary
-        # (using explicit default to override global argument_default)
-        if '-' in prefix_chars:
-            default_prefix = '-'
-        else:
-            default_prefix = prefix_chars[0]
-        if self.add_help:
-            self.add_argument(
-                default_prefix+'h', default_prefix*2+'help',
-                action='help', default=SUPPRESS,
-                help=_('show this help message and exit'))
-        if self.version:
-            self.add_argument(
-                default_prefix+'v', default_prefix*2+'version',
-                action='version', default=SUPPRESS,
-                version=self.version,
-                help=_("show program's version number and exit"))
-
-        # add parent arguments and defaults
-        for parent in parents:
-            self._add_container_actions(parent)
-            try:
-                defaults = parent._defaults
-            except AttributeError:
-                pass
-            else:
-                self._defaults.update(defaults)
-
-    # =======================
-    # Pretty __repr__ methods
-    # =======================
-    def _get_kwargs(self):
-        names = [
-            'prog',
-            'usage',
-            'description',
-            'version',
-            'formatter_class',
-            'conflict_handler',
-            'add_help',
-        ]
-        return [(name, getattr(self, name)) for name in names]
-
-    # ==================================
-    # Optional/Positional adding methods
-    # ==================================
-    def add_subparsers(self, **kwargs):
-        if self._subparsers is not None:
-            self.error(_('cannot have multiple subparser arguments'))
-
-        # add the parser class to the arguments if it's not present
-        kwargs.setdefault('parser_class', type(self))
-
-        if 'title' in kwargs or 'description' in kwargs:
-            title = _(kwargs.pop('title', 'subcommands'))
-            description = _(kwargs.pop('description', None))
-            self._subparsers = self.add_argument_group(title, description)
-        else:
-            self._subparsers = self._positionals
-
-        # prog defaults to the usage message of this parser, skipping
-        # optional arguments and with no "usage:" prefix
-        if kwargs.get('prog') is None:
-            formatter = self._get_formatter()
-            positionals = self._get_positional_actions()
-            groups = self._mutually_exclusive_groups
-            formatter.add_usage(self.usage, positionals, groups, '')
-            kwargs['prog'] = formatter.format_help().strip()
-
-        # create the parsers action and add it to the positionals list
-        parsers_class = self._pop_action_class(kwargs, 'parsers')
-        action = parsers_class(option_strings=[], **kwargs)
-        self._subparsers._add_action(action)
-
-        # return the created parsers action
-        return action
-
-    def _add_action(self, action):
-        if action.option_strings:
-            self._optionals._add_action(action)
-        else:
-            self._positionals._add_action(action)
-        return action
-
-    def _get_optional_actions(self):
-        return [action
-                for action in self._actions
-                if action.option_strings]
-
-    def _get_positional_actions(self):
-        return [action
-                for action in self._actions
-                if not action.option_strings]
-
-    # =====================================
-    # Command line argument parsing methods
-    # =====================================
-    def parse_args(self, args=None, namespace=None):
-        args, argv = self.parse_known_args(args, namespace)
-        if argv:
-            msg = _('unrecognized arguments: %s')
-            self.error(msg % ' '.join(argv))
-        return args
-
-    def parse_known_args(self, args=None, namespace=None):
-        # args default to the system args
-        if args is None:
-            args = _sys.argv[1:]
-
-        # default Namespace built from parser defaults
-        if namespace is None:
-            namespace = Namespace()
-
-        # add any action defaults that aren't present
-        for action in self._actions:
-            if action.dest is not SUPPRESS:
-                if not hasattr(namespace, action.dest):
-                    if action.default is not SUPPRESS:
-                        setattr(namespace, action.dest, action.default)
-
-        # add any parser defaults that aren't present
-        for dest in self._defaults:
-            if not hasattr(namespace, dest):
-                setattr(namespace, dest, self._defaults[dest])
-
-        # parse the arguments and exit if there are any errors
-        try:
-            namespace, args = self._parse_known_args(args, namespace)
-            if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
-                args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
-                delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
-            return namespace, args
-        except ArgumentError:
-            err = _sys.exc_info()[1]
-            self.error(str(err))
-
-    def _parse_known_args(self, arg_strings, namespace):
-        # replace arg strings that are file references
-        if self.fromfile_prefix_chars is not None:
-            arg_strings = self._read_args_from_files(arg_strings)
-
-        # map all mutually exclusive arguments to the other arguments
-        # they can't occur with
-        action_conflicts = {}
-        for mutex_group in self._mutually_exclusive_groups:
-            group_actions = mutex_group._group_actions
-            for i, mutex_action in enumerate(mutex_group._group_actions):
-                conflicts = action_conflicts.setdefault(mutex_action, [])
-                conflicts.extend(group_actions[:i])
-                conflicts.extend(group_actions[i + 1:])
-
-        # find all option indices, and determine the arg_string_pattern
-        # which has an 'O' if there is an option at an index,
-        # an 'A' if there is an argument, or a '-' if there is a '--'
-        option_string_indices = {}
-        arg_string_pattern_parts = []
-        arg_strings_iter = iter(arg_strings)
-        for i, arg_string in enumerate(arg_strings_iter):
-
-            # all args after -- are non-options
-            if arg_string == '--':
-                arg_string_pattern_parts.append('-')
-                for arg_string in arg_strings_iter:
-                    arg_string_pattern_parts.append('A')
-
-            # otherwise, add the arg to the arg strings
-            # and note the index if it was an option
-            else:
-                option_tuple = self._parse_optional(arg_string)
-                if option_tuple is None:
-                    pattern = 'A'
-                else:
-                    option_string_indices[i] = option_tuple
-                    pattern = 'O'
-                arg_string_pattern_parts.append(pattern)
-
-        # join the pieces together to form the pattern
-        arg_strings_pattern = ''.join(arg_string_pattern_parts)
-
-        # converts arg strings to the appropriate and then takes the action
-        seen_actions = set()
-        seen_non_default_actions = set()
-
-        def take_action(action, argument_strings, option_string=None):
-            seen_actions.add(action)
-            argument_values = self._get_values(action, argument_strings)
-
-            # error if this argument is not allowed with other previously
-            # seen arguments, assuming that actions that use the default
-            # value don't really count as "present"
-            if argument_values is not action.default:
-                seen_non_default_actions.add(action)
-                for conflict_action in action_conflicts.get(action, []):
-                    if conflict_action in seen_non_default_actions:
-                        msg = _('not allowed with argument %s')
-                        action_name = _get_action_name(conflict_action)
-                        raise ArgumentError(action, msg % action_name)
-
-            # take the action if we didn't receive a SUPPRESS value
-            # (e.g. from a default)
-            if argument_values is not SUPPRESS:
-                action(self, namespace, argument_values, option_string)
-
-        # function to convert arg_strings into an optional action
-        def consume_optional(start_index):
-
-            # get the optional identified at this index
-            option_tuple = option_string_indices[start_index]
-            action, option_string, explicit_arg = option_tuple
-
-            # identify additional optionals in the same arg string
-            # (e.g. -xyz is the same as -x -y -z if no args are required)
-            match_argument = self._match_argument
-            action_tuples = []
-            while True:
-
-                # if we found no optional action, skip it
-                if action is None:
-                    extras.append(arg_strings[start_index])
-                    return start_index + 1
-
-                # if there is an explicit argument, try to match the
-                # optional's string arguments to only this
-                if explicit_arg is not None:
-                    arg_count = match_argument(action, 'A')
-
-                    # if the action is a single-dash option and takes no
-                    # arguments, try to parse more single-dash options out
-                    # of the tail of the option string
-                    chars = self.prefix_chars
-                    if arg_count == 0 and option_string[1] not in chars:
-                        action_tuples.append((action, [], option_string))
-                        char = option_string[0]
-                        option_string = char + explicit_arg[0]
-                        new_explicit_arg = explicit_arg[1:] or None
-                        optionals_map = self._option_string_actions
-                        if option_string in optionals_map:
-                            action = optionals_map[option_string]
-                            explicit_arg = new_explicit_arg
-                        else:
-                            msg = _('ignored explicit argument %r')
-                            raise ArgumentError(action, msg % explicit_arg)
-
-                    # if the action expect exactly one argument, we've
-                    # successfully matched the option; exit the loop
-                    elif arg_count == 1:
-                        stop = start_index + 1
-                        args = [explicit_arg]
-                        action_tuples.append((action, args, option_string))
-                        break
-
-                    # error if a double-dash option did not use the
-                    # explicit argument
-                    else:
-                        msg = _('ignored explicit argument %r')
-                        raise ArgumentError(action, msg % explicit_arg)
-
-                # if there is no explicit argument, try to match the
-                # optional's string arguments with the following strings
-                # if successful, exit the loop
-                else:
-                    start = start_index + 1
-                    selected_patterns = arg_strings_pattern[start:]
-                    arg_count = match_argument(action, selected_patterns)
-                    stop = start + arg_count
-                    args = arg_strings[start:stop]
-                    action_tuples.append((action, args, option_string))
-                    break
-
-            # add the Optional to the list and return the index at which
-            # the Optional's string args stopped
-            assert action_tuples
-            for action, args, option_string in action_tuples:
-                take_action(action, args, option_string)
-            return stop
-
-        # the list of Positionals left to be parsed; this is modified
-        # by consume_positionals()
-        positionals = self._get_positional_actions()
-
-        # function to convert arg_strings into positional actions
-        def consume_positionals(start_index):
-            # match as many Positionals as possible
-            match_partial = self._match_arguments_partial
-            selected_pattern = arg_strings_pattern[start_index:]
-            arg_counts = match_partial(positionals, selected_pattern)
-
-            # slice off the appropriate arg strings for each Positional
-            # and add the Positional and its args to the list
-            for action, arg_count in zip(positionals, arg_counts):
-                args = arg_strings[start_index: start_index + arg_count]
-                start_index += arg_count
-                take_action(action, args)
-
-            # slice off the Positionals that we just parsed and return the
-            # index at which the Positionals' string args stopped
-            positionals[:] = positionals[len(arg_counts):]
-            return start_index
-
-        # consume Positionals and Optionals alternately, until we have
-        # passed the last option string
-        extras = []
-        start_index = 0
-        if option_string_indices:
-            max_option_string_index = max(option_string_indices)
-        else:
-            max_option_string_index = -1
-        while start_index <= max_option_string_index:
-
-            # consume any Positionals preceding the next option
-            next_option_string_index = min([
-                index
-                for index in option_string_indices
-                if index >= start_index])
-            if start_index != next_option_string_index:
-                positionals_end_index = consume_positionals(start_index)
-
-                # only try to parse the next optional if we didn't consume
-                # the option string during the positionals parsing
-                if positionals_end_index > start_index:
-                    start_index = positionals_end_index
-                    continue
-                else:
-                    start_index = positionals_end_index
-
-            # if we consumed all the positionals we could and we're not
-            # at the index of an option string, there were extra arguments
-            if start_index not in option_string_indices:
-                strings = arg_strings[start_index:next_option_string_index]
-                extras.extend(strings)
-                start_index = next_option_string_index
-
-            # consume the next optional and any arguments for it
-            start_index = consume_optional(start_index)
-
-        # consume any positionals following the last Optional
-        stop_index = consume_positionals(start_index)
-
-        # if we didn't consume all the argument strings, there were extras
-        extras.extend(arg_strings[stop_index:])
-
-        # if we didn't use all the Positional objects, there were too few
-        # arg strings supplied.
-        if positionals:
-            self.error(_('too few arguments'))
-
-        # make sure all required actions were present, and convert defaults.
-        for action in self._actions:
-            if action not in seen_actions:
-                if action.required:
-                    name = _get_action_name(action)
-                    self.error(_('argument %s is required') % name)
-                else:
-                    # Convert action default now instead of doing it before
-                    # parsing arguments to avoid calling convert functions
-                    # twice (which may fail) if the argument was given, but
-                    # only if it was defined already in the namespace
-                    if (action.default is not None and
-                            isinstance(action.default, basestring) and
-                            hasattr(namespace, action.dest) and
-                            action.default is getattr(namespace, action.dest)):
-                        setattr(namespace, action.dest,
-                                self._get_value(action, action.default))
-
-        # make sure all required groups had one option present
-        for group in self._mutually_exclusive_groups:
-            if group.required:
-                for action in group._group_actions:
-                    if action in seen_non_default_actions:
-                        break
-
-                # if no actions were used, report the error
-                else:
-                    names = [_get_action_name(action)
-                             for action in group._group_actions
-                             if action.help is not SUPPRESS]
-                    msg = _('one of the arguments %s is required')
-                    self.error(msg % ' '.join(names))
-
-        # return the updated namespace and the extra arguments
-        return namespace, extras
-
-    def _read_args_from_files(self, arg_strings):
-        # expand arguments referencing files
-        new_arg_strings = []
-        for arg_string in arg_strings:
-
-            # for regular arguments, just add them back into the list
-            if arg_string[0] not in self.fromfile_prefix_chars:
-                new_arg_strings.append(arg_string)
-
-            # replace arguments referencing files with the file content
-            else:
-                try:
-                    args_file = open(arg_string[1:])
-                    try:
-                        arg_strings = []
-                        for arg_line in args_file.read().splitlines():
-                            for arg in self.convert_arg_line_to_args(arg_line):
-                                arg_strings.append(arg)
-                        arg_strings = self._read_args_from_files(arg_strings)
-                        new_arg_strings.extend(arg_strings)
-                    finally:
-                        args_file.close()
-                except IOError:
-                    err = _sys.exc_info()[1]
-                    self.error(str(err))
-
-        # return the modified argument list
-        return new_arg_strings
-
-    def convert_arg_line_to_args(self, arg_line):
-        return [arg_line]
-
-    def _match_argument(self, action, arg_strings_pattern):
-        # match the pattern for this action to the arg strings
-        nargs_pattern = self._get_nargs_pattern(action)
-        match = _re.match(nargs_pattern, arg_strings_pattern)
-
-        # raise an exception if we weren't able to find a match
-        if match is None:
-            nargs_errors = {
-                None: _('expected one argument'),
-                OPTIONAL: _('expected at most one argument'),
-                ONE_OR_MORE: _('expected at least one argument'),
-            }
-            default = _('expected %s argument(s)') % action.nargs
-            msg = nargs_errors.get(action.nargs, default)
-            raise ArgumentError(action, msg)
-
-        # return the number of arguments matched
-        return len(match.group(1))
-
-    def _match_arguments_partial(self, actions, arg_strings_pattern):
-        # progressively shorten the actions list by slicing off the
-        # final actions until we find a match
-        result = []
-        for i in range(len(actions), 0, -1):
-            actions_slice = actions[:i]
-            pattern = ''.join([self._get_nargs_pattern(action)
-                               for action in actions_slice])
-            match = _re.match(pattern, arg_strings_pattern)
-            if match is not None:
-                result.extend([len(string) for string in match.groups()])
-                break
-
-        # return the list of arg string counts
-        return result
-
-    def _parse_optional(self, arg_string):
-        # if it's an empty string, it was meant to be a positional
-        if not arg_string:
-            return None
-
-        # if it doesn't start with a prefix, it was meant to be positional
-        if not arg_string[0] in self.prefix_chars:
-            return None
-
-        # if the option string is present in the parser, return the action
-        if arg_string in self._option_string_actions:
-            action = self._option_string_actions[arg_string]
-            return action, arg_string, None
-
-        # if it's just a single character, it was meant to be positional
-        if len(arg_string) == 1:
-            return None
-
-        # if the option string before the "=" is present, return the action
-        if '=' in arg_string:
-            option_string, explicit_arg = arg_string.split('=', 1)
-            if option_string in self._option_string_actions:
-                action = self._option_string_actions[option_string]
-                return action, option_string, explicit_arg
-
-        # search through all possible prefixes of the option string
-        # and all actions in the parser for possible interpretations
-        option_tuples = self._get_option_tuples(arg_string)
-
-        # if multiple actions match, the option string was ambiguous
-        if len(option_tuples) > 1:
-            options = ', '.join([option_string
-                for action, option_string, explicit_arg in option_tuples])
-            tup = arg_string, options
-            self.error(_('ambiguous option: %s could match %s') % tup)
-
-        # if exactly one action matched, this segmentation is good,
-        # so return the parsed action
-        elif len(option_tuples) == 1:
-            option_tuple, = option_tuples
-            return option_tuple
-
-        # if it was not found as an option, but it looks like a negative
-        # number, it was meant to be positional
-        # unless there are negative-number-like options
-        if self._negative_number_matcher.match(arg_string):
-            if not self._has_negative_number_optionals:
-                return None
-
-        # if it contains a space, it was meant to be a positional
-        if ' ' in arg_string:
-            return None
-
-        # it was meant to be an optional but there is no such option
-        # in this parser (though it might be a valid option in a subparser)
-        return None, arg_string, None
-
-    def _get_option_tuples(self, option_string):
-        result = []
-
-        # option strings starting with two prefix characters are only
-        # split at the '='
-        chars = self.prefix_chars
-        if option_string[0] in chars and option_string[1] in chars:
-            if '=' in option_string:
-                option_prefix, explicit_arg = option_string.split('=', 1)
-            else:
-                option_prefix = option_string
-                explicit_arg = None
-            for option_string in self._option_string_actions:
-                if option_string.startswith(option_prefix):
-                    action = self._option_string_actions[option_string]
-                    tup = action, option_string, explicit_arg
-                    result.append(tup)
-
-        # single character options can be concatenated with their arguments
-        # but multiple character options always have to have their argument
-        # separate
-        elif option_string[0] in chars and option_string[1] not in chars:
-            option_prefix = option_string
-            explicit_arg = None
-            short_option_prefix = option_string[:2]
-            short_explicit_arg = option_string[2:]
-
-            for option_string in self._option_string_actions:
-                if option_string == short_option_prefix:
-                    action = self._option_string_actions[option_string]
-                    tup = action, option_string, short_explicit_arg
-                    result.append(tup)
-                elif option_string.startswith(option_prefix):
-                    action = self._option_string_actions[option_string]
-                    tup = action, option_string, explicit_arg
-                    result.append(tup)
-
-        # shouldn't ever get here
-        else:
-            self.error(_('unexpected option string: %s') % option_string)
-
-        # return the collected option tuples
-        return result
-
-    def _get_nargs_pattern(self, action):
-        # in all examples below, we have to allow for '--' args
-        # which are represented as '-' in the pattern
-        nargs = action.nargs
-
-        # the default (None) is assumed to be a single argument
-        if nargs is None:
-            nargs_pattern = '(-*A-*)'
-
-        # allow zero or one arguments
-        elif nargs == OPTIONAL:
-            nargs_pattern = '(-*A?-*)'
-
-        # allow zero or more arguments
-        elif nargs == ZERO_OR_MORE:
-            nargs_pattern = '(-*[A-]*)'
-
-        # allow one or more arguments
-        elif nargs == ONE_OR_MORE:
-            nargs_pattern = '(-*A[A-]*)'
-
-        # allow any number of options or arguments
-        elif nargs == REMAINDER:
-            nargs_pattern = '([-AO]*)'
-
-        # allow one argument followed by any number of options or arguments
-        elif nargs == PARSER:
-            nargs_pattern = '(-*A[-AO]*)'
-
-        # all others should be integers
-        else:
-            nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
-
-        # if this is an optional action, -- is not allowed
-        if action.option_strings:
-            nargs_pattern = nargs_pattern.replace('-*', '')
-            nargs_pattern = nargs_pattern.replace('-', '')
-
-        # return the pattern
-        return nargs_pattern
-
-    # ========================
-    # Value conversion methods
-    # ========================
-    def _get_values(self, action, arg_strings):
-        # for everything but PARSER args, strip out '--'
-        if action.nargs not in [PARSER, REMAINDER]:
-            arg_strings = [s for s in arg_strings if s != '--']
-
-        # optional argument produces a default when not present
-        if not arg_strings and action.nargs == OPTIONAL:
-            if action.option_strings:
-                value = action.const
-            else:
-                value = action.default
-            if isinstance(value, basestring):
-                value = self._get_value(action, value)
-                self._check_value(action, value)
-
-        # when nargs='*' on a positional, if there were no command-line
-        # args, use the default if it is anything other than None
-        elif (not arg_strings and action.nargs == ZERO_OR_MORE and
-              not action.option_strings):
-            if action.default is not None:
-                value = action.default
-            else:
-                value = arg_strings
-            self._check_value(action, value)
-
-        # single argument or optional argument produces a single value
-        elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
-            arg_string, = arg_strings
-            value = self._get_value(action, arg_string)
-            self._check_value(action, value)
-
-        # REMAINDER arguments convert all values, checking none
-        elif action.nargs == REMAINDER:
-            value = [self._get_value(action, v) for v in arg_strings]
-
-        # PARSER arguments convert all values, but check only the first
-        elif action.nargs == PARSER:
-            value = [self._get_value(action, v) for v in arg_strings]
-            self._check_value(action, value[0])
-
-        # all other types of nargs produce a list
-        else:
-            value = [self._get_value(action, v) for v in arg_strings]
-            for v in value:
-                self._check_value(action, v)
-
-        # return the converted value
-        return value
-
-    def _get_value(self, action, arg_string):
-        type_func = self._registry_get('type', action.type, action.type)
-        if not _callable(type_func):
-            msg = _('%r is not callable')
-            raise ArgumentError(action, msg % type_func)
-
-        # convert the value to the appropriate type
-        try:
-            result = type_func(arg_string)
-
-        # ArgumentTypeErrors indicate errors
-        except ArgumentTypeError:
-            name = getattr(action.type, '__name__', repr(action.type))
-            msg = str(_sys.exc_info()[1])
-            raise ArgumentError(action, msg)
-
-        # TypeErrors or ValueErrors also indicate errors
-        except (TypeError, ValueError):
-            name = getattr(action.type, '__name__', repr(action.type))
-            msg = _('invalid %s value: %r')
-            raise ArgumentError(action, msg % (name, arg_string))
-
-        # return the converted value
-        return result
-
-    def _check_value(self, action, value):
-        # converted value must be one of the choices (if specified)
-        if action.choices is not None and value not in action.choices:
-            tup = value, ', '.join(map(repr, action.choices))
-            msg = _('invalid choice: %r (choose from %s)') % tup
-            raise ArgumentError(action, msg)
-
-    # =======================
-    # Help-formatting methods
-    # =======================
-    def format_usage(self):
-        formatter = self._get_formatter()
-        formatter.add_usage(self.usage, self._actions,
-                            self._mutually_exclusive_groups)
-        return formatter.format_help()
-
-    def format_help(self):
-        formatter = self._get_formatter()
-
-        # usage
-        formatter.add_usage(self.usage, self._actions,
-                            self._mutually_exclusive_groups)
-
-        # description
-        formatter.add_text(self.description)
-
-        # positionals, optionals and user-defined groups
-        for action_group in self._action_groups:
-            formatter.start_section(action_group.title)
-            formatter.add_text(action_group.description)
-            formatter.add_arguments(action_group._group_actions)
-            formatter.end_section()
-
-        # epilog
-        formatter.add_text(self.epilog)
-
-        # determine help from format above
-        return formatter.format_help()
-
-    def format_version(self):
-        import warnings
-        warnings.warn(
-            'The format_version method is deprecated -- the "version" '
-            'argument to ArgumentParser is no longer supported.',
-            DeprecationWarning)
-        formatter = self._get_formatter()
-        formatter.add_text(self.version)
-        return formatter.format_help()
-
-    def _get_formatter(self):
-        return self.formatter_class(prog=self.prog)
-
-    # =====================
-    # Help-printing methods
-    # =====================
-    def print_usage(self, file=None):
-        if file is None:
-            file = _sys.stdout
-        self._print_message(self.format_usage(), file)
-
-    def print_help(self, file=None):
-        if file is None:
-            file = _sys.stdout
-        self._print_message(self.format_help(), file)
-
-    def print_version(self, file=None):
-        import warnings
-        warnings.warn(
-            'The print_version method is deprecated -- the "version" '
-            'argument to ArgumentParser is no longer supported.',
-            DeprecationWarning)
-        self._print_message(self.format_version(), file)
-
-    def _print_message(self, message, file=None):
-        if message:
-            if file is None:
-                file = _sys.stderr
-            file.write(message)
-
-    # ===============
-    # Exiting methods
-    # ===============
-    def exit(self, status=0, message=None):
-        if message:
-            self._print_message(message, _sys.stderr)
-        _sys.exit(status)
-
-    def error(self, message):
-        """error(message: string)
-
-        Prints a usage message incorporating the message to stderr and
-        exits.
-
-        If you override this in a subclass, it should not return -- it
-        should either exit or raise an exception.
-        """
-        self.print_usage(_sys.stderr)
-        self.exit(2, _('%s: error: %s\n') % (self.prog, message))
diff --git a/keycodemapdb/tools/keymap-gen b/keycodemapdb/tools/keymap-gen
deleted file mode 100755
index 22b4f71..0000000
--- a/keycodemapdb/tools/keymap-gen
+++ /dev/null
@@ -1,1147 +0,0 @@
-#!/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
-try:
-    import argparse
-except:
-    import os, sys
-    sys.path.append(os.path.join(os.path.dirname(__file__), "../thirdparty"))
-    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"
-
-    # QEMU key numbers: xtkbd + special re-encoding of high bit
-    MAP_QNUM = "qnum"
-
-    # HTML codes
-    MAP_HTML = "html"
-
-    # XKB key names
-    MAP_XKB = "xkb"
-
-    # QEMU keycodes
-    MAP_QCODE = "qcode"
-
-    # Sun / Sparc  scan codes
-    # Reference: "SPARC International Keyboard Spec 1", page 7 "US scan set"
-    MAP_SUN = "sun"
-
-    # Apple Desktop Bus
-    # Reference: http://www.archive.org/stream/apple-guide-macintosh-family-hardware/Apple_Guide_to_the_Macintosh_Family_Hardware_2e#page/n345/mode/2up
-    MAP_ADB = "adb"
-
-    MAP_LIST = (
-        MAP_LINUX,
-        MAP_OSX,
-        MAP_ATSET1,
-        MAP_ATSET2,
-        MAP_ATSET3,
-        MAP_USB,
-        MAP_WIN32,
-        MAP_XWINXT,
-        MAP_XKBDXT,
-        MAP_X11,
-        MAP_HTML,
-        MAP_XKB,
-        MAP_QCODE,
-        MAP_SUN,
-        MAP_ADB,
-
-        # These are derived from maps above
-        MAP_XTKBD,
-        MAP_XORGEVDEV,
-        MAP_XORGKBD,
-        MAP_XORGXQUARTZ,
-        MAP_XORGXWIN,
-        MAP_QNUM,
-    )
-
-    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,
-        MAP_HTML: 14,
-        MAP_XKB: 15,
-        MAP_SUN: 17,
-        MAP_ADB: 18,
-    }
-
-    ENUM_COLUMNS = {
-        MAP_QCODE: 14,
-    }
-
-    NAME_COLUMNS = {
-        MAP_LINUX: 0,
-        MAP_OSX: 2,
-        MAP_WIN32: 8,
-        MAP_X11: 12,
-        MAP_HTML: 14,
-        MAP_XKB: 15,
-        MAP_QCODE: 16,
-    }
-
-    ENUM_BOUND = {
-        MAP_QCODE: "Q_KEY_CODE__MAX",
-    }
-
-    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)
-            elif val.isdigit():
-                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
-
-        # QNUM 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)
-                qnum = 0x80 | (at1 & 0x7f)
-            else:
-                qnum = at1
-            self.mapto[self.MAP_QNUM][linux] = qnum
-            self.mapfrom[self.MAP_QNUM][qnum] = linux
-
-            # Hack for compatibility with previous mistakes in handling
-            # Print/SysRq. The preferred qnum for Print/SysRq is 0x54,
-            # but QEMU previously allowed 0xb7 too
-            if qnum == 0x54:
-                self.mapfrom[self.MAP_QNUM][0xb7] = self.mapfrom[self.MAP_QNUM][0x54]
-
-        if linux in self.mapname[self.MAP_QCODE]:
-            qcodeenum = self.mapname[self.MAP_QCODE][linux]
-            qcodeenum = "Q_KEY_CODE_" + qcodeenum.upper()
-            self.mapto[self.MAP_QCODE][linux] = qcodeenum
-            self.mapfrom[self.MAP_QCODE][qcodeenum] = linux
-
-class LanguageGenerator(object):
-
-    def _boilerplate(self, lines):
-        raise NotImplementedError()
-
-    def generate_header(self, database, args):
-        self._boilerplate([
-            "This file is auto-generated from keymaps.csv",
-            "Database checksum sha256(%s)" % database.mapchecksum,
-            "To re-generate, run:",
-            "  %s" % args,
-        ])
-
-class LanguageSrcGenerator(LanguageGenerator):
-
-    TYPE_INT = "integer"
-    TYPE_STRING = "string"
-    TYPE_ENUM = "enum"
-
-    def _array_start(self, varname, length, defvalue, fromtype, totype):
-        raise NotImplementedError()
-
-    def _array_end(self, fromtype, totype):
-        raise NotImplementedError()
-
-    def _array_entry(self, index, value, comment, fromtype, totype):
-        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)
-
-        if frommapname in database.ENUM_COLUMNS:
-            fromtype = self.TYPE_ENUM
-        elif type(list(tolinux.keys())[0]) == str:
-            fromtype = self.TYPE_STRING
-        else:
-            fromtype = self.TYPE_INT
-
-        if tomapname in database.ENUM_COLUMNS:
-            totype = self.TYPE_ENUM
-        elif type(list(fromlinux.values())[0]) == str:
-            totype = self.TYPE_STRING
-        else:
-            totype = self.TYPE_INT
-
-        keys = list(tolinux.keys())
-        keys.sort()
-        if fromtype == self.TYPE_INT:
-            keys = range(keys[-1] + 1)
-
-        if fromtype == self.TYPE_ENUM:
-            keymax = database.ENUM_BOUND[frommapname]
-        else:
-            keymax = len(keys)
-
-        defvalue = fromlinux.get(0, None)
-        if fromtype == self.TYPE_ENUM:
-            self._array_start(varname, keymax, defvalue, fromtype, totype)
-        else:
-            self._array_start(varname, keymax, None, fromtype, totype)
-
-        for src in keys:
-            linux = tolinux.get(src, None)
-            if linux is None:
-                dst = None
-            else:
-                dst = fromlinux.get(linux, defvalue)
-
-            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(src, dst, comment, fromtype, totype)
-        self._array_end(fromtype, totype)
-
-    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 = list(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
-
-        if mapname in database.ENUM_COLUMNS:
-            totype = self.TYPE_ENUM
-        elif type(list(database.mapto[mapname].values())[0]) == str:
-            totype = self.TYPE_STRING
-        else:
-            totype = self.TYPE_INT
-
-        self._array_start(varname, len(keys), None, self.TYPE_INT, totype)
-
-        defvalue = database.mapto[mapname].get(0, None)
-        for i in range(len(keys)):
-            key = keys[i]
-            dst = database.mapto[mapname].get(key, defvalue)
-            self._array_entry(i, dst, names[i], self.TYPE_INT, totype)
-
-        self._array_end(self.TYPE_INT, totype)
-
-    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)
-
-        keys = list(tolinux.keys())
-        keys.sort()
-        if type(keys[0]) == int:
-            keys = range(keys[-1] + 1)
-
-        if type(keys[0]) == int:
-            fromtype = self.TYPE_INT
-        else:
-            fromtype = self.TYPE_STRING
-
-        self._array_start(varname, len(keys), None, fromtype, self.TYPE_STRING)
-
-        for src in keys:
-            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(src, dst, comment, fromtype, self.TYPE_STRING)
-        self._array_end(fromtype, self.TYPE_STRING)
-
-    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 = list(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(varname, len(keys), None, self.TYPE_INT, self.TYPE_STRING)
-
-        for i in range(len(keys)):
-            key = keys[i]
-            dst = database.mapname[mapname].get(key, None)
-            self._array_entry(i, dst, names[i], self.TYPE_INT, self.TYPE_STRING)
-
-        self._array_end(self.TYPE_INT, self.TYPE_STRING)
-
-    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, title, subtitle, database, mapname):
-        if mapname not in database.mapname:
-            raise Exception("Unknown map %s, expected one of %s" % (
-                            mapname, ", ".join(database.mapname.keys())))
-
-        keys = list(database.mapto[Database.MAP_LINUX].keys())
-        keys.sort()
-        names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys]
-
-        if title is None:
-            title = mapname
-        if subtitle is None:
-            subtitle = "Docs for %s" % mapname
-
-        self._array_start_name_doc(title, subtitle, 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, title, subtitle, 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 = list(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 title is None:
-            title = mapname
-        if subtitle is None:
-            subtitle = "Docs for %s" % mapname
-
-        self._array_start_code_doc(title, subtitle, 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, lentypename):
-        self.inttypename = inttypename
-        self.strtypename = strtypename
-        self.lentypename = lentypename
-
-    def _boilerplate(self, lines):
-        print("/*")
-        for line in lines:
-            print(" * %s" % line)
-        print("*/")
-
-    def _array_start(self, varname, length, defvalue, fromtype, totype):
-        self._varname = varname;
-        totypename = self.strtypename if totype == self.TYPE_STRING else self.inttypename
-        if fromtype in (self.TYPE_INT, self.TYPE_ENUM):
-            if type(length) == str:
-                print("const %s %s[%s] = {" % (totypename, varname, length))
-            else:
-                print("const %s %s[%d] = {" % (totypename, varname, length))
-        else:
-            print("const struct _%s {" % varname)
-            print("  const %s from;" % self.strtypename)
-            print("  const %s to;" % totypename)
-            print("} %s[] = {" % varname)
-
-        if defvalue != None:
-            if totype == self.TYPE_ENUM:
-                if type(length) == str:
-                    print("  [0 ... %s-1] = %s," % (length, defvalue))
-                else:
-                    print("  [0 ... 0x%x-1] = %s," % (length, defvalue))
-            else:
-                if type(length) == str:
-                    print("  [0 ... %s-1] = 0x%x," % (length, defvalue))
-                else:
-                    print("  [0 ... 0x%x-1] = 0x%x," % (length, defvalue))
-
-    def _array_end(self, fromtype, totype):
-        print("};")
-        print("const %s %s_len = sizeof(%s)/sizeof(%s[0]);" %
-              (self.lentypename, self._varname, self._varname, self._varname))
-
-    def _array_entry(self, index, value, comment, fromtype, totype):
-        if value is None:
-            return
-        if fromtype == self.TYPE_INT:
-            indexfmt = "0x%x"
-        elif fromtype == self.TYPE_ENUM:
-            indexfmt = "%s"
-        else:
-            indexfmt = "\"%s\""
-
-        if totype == self.TYPE_INT:
-            valuefmt = "0x%x"
-        elif totype == self.TYPE_ENUM:
-            valuefmt = "%s"
-        else:
-            valuefmt = "\"%s\""
-
-        if fromtype != self.TYPE_STRING:
-            print(("  [" + indexfmt + "] = " + valuefmt + ", /* %s */") % (index, value, comment))
-        else:
-            print(("  {" + indexfmt + ", " + valuefmt + "}, /* %s */") % (index, value, comment))
-
-class StdCLanguageGenerator(CLanguageGenerator):
-
-    def __init__(self):
-        super(StdCLanguageGenerator, self).__init__("unsigned short", "char *", "unsigned int")
-
-class GLib2LanguageGenerator(CLanguageGenerator):
-
-    def __init__(self):
-        super(GLib2LanguageGenerator, self).__init__("guint16", "gchar *", "guint")
-
-class CHeaderLanguageGenerator(LanguageSrcGenerator):
-
-    def __init__(self, inttypename, strtypename, lentypename):
-        self.inttypename = inttypename
-        self.strtypename = strtypename
-        self.lentypename = lentypename
-
-    def _boilerplate(self, lines):
-        print("/*")
-        for line in lines:
-            print(" * %s" % line)
-        print("*/")
-
-    def _array_start(self, varname, length, defvalue, fromtype, totype):
-        self._varname = varname
-        if fromtype == self.TYPE_STRING:
-            self._length = 0
-        else:
-            self._length = length
-
-    def _array_end(self, fromtype, totype):
-        totypename = self.strtypename if totype == self.TYPE_STRING else self.inttypename
-        if fromtype == self.TYPE_STRING:
-            vartypename = "struct _%s" % self._varname
-            print("%s {" % vartypename)
-            print("  const %s from;" % self.strtypename)
-            print("  const %s to;" % totypename)
-            print("};")
-        else:
-            vartypename = totypename
-        if type(self._length) == str:
-            print("extern const %s %s[%s];" % (vartypename, self._varname, self._length))
-        else:
-            print("extern const %s %s[%d];" % (vartypename, self._varname, self._length))
-        print("extern const %s %s_len;" % (self.lentypename, self._varname))
-
-    def _array_entry(self, index, value, comment, fromtype, totype):
-        if value is None:
-            return
-        if fromtype == self.TYPE_STRING:
-            self._length += 1
-
-class StdCHeaderLanguageGenerator(CHeaderLanguageGenerator):
-
-    def __init__(self):
-        super(StdCHeaderLanguageGenerator, self).__init__("unsigned short", "char *", "unsigned int")
-
-class GLib2HeaderLanguageGenerator(CHeaderLanguageGenerator):
-
-    def __init__(self):
-        super(GLib2HeaderLanguageGenerator, self).__init__("guint16", "gchar *", "guint")
-
-class CppLanguageGenerator(CLanguageGenerator):
-
-    def _array_start(self, varname, length, defvalue, fromtype, totype):
-        if fromtype == self.TYPE_ENUM:
-            raise NotImplementedError("Enums not supported as source in C++ generator")
-        totypename = "const " + self.strtypename if totype == self.TYPE_STRING else self.inttypename
-        if fromtype == self.TYPE_INT:
-            print("#include <vector>")
-            print("extern const std::vector<%s> %s;" % (totypename, varname));
-            print("const std::vector<%s> %s = {" % (totypename, varname))
-        else:
-            print("#include <map>")
-            print("#include <string>")
-            print("extern const std::map<const std::string, %s> %s;" % (totypename, varname))
-            print("const std::map<const std::string, %s> %s = {" % (totypename, varname))
-
-    def _array_end(self, fromtype, totype):
-        print("};")
-
-    # designated initializers not available in C++
-    def _array_entry(self, index, value, comment, fromtype, totype):
-        if fromtype == self.TYPE_STRING:
-            return super(CppLanguageGenerator, self)._array_entry(index, value, comment, fromtype, totype)
-
-        if value is None:
-            print("  0, /* %s */" % comment)
-        elif totype == self.TYPE_INT:
-            print("  0x%x, /* %s */" % (value, comment))
-        elif totype == self.TYPE_ENUM:
-            print("  %s, /* %s */" % (value, comment))
-        else:
-            print("  \"%s\", /* %s */" % (value, comment))
-
-class StdCppLanguageGenerator(CppLanguageGenerator):
-
-    def __init__(self):
-        super(StdCppLanguageGenerator, self).__init__("unsigned short", "char *", "unsigned int")
-
-class CppHeaderLanguageGenerator(CHeaderLanguageGenerator):
-
-    def _array_start(self, varname, length, defvalue, fromtype, totype):
-        if fromtype == self.TYPE_ENUM:
-            raise NotImplementedError("Enums not supported as source in C++ generator")
-        totypename = "const " + self.strtypename if totype == self.TYPE_STRING else self.inttypename
-        if fromtype == self.TYPE_INT:
-            print("#include <vector>")
-            print("extern const std::vector<%s> %s;" % (totypename, varname));
-        else:
-            print("#include <map>")
-            print("#include <string>")
-            print("extern const std::map<const std::string, %s> %s;" % (totypename, varname))
-
-    def _array_end(self, fromtype, totype):
-        pass
-
-    # designated initializers not available in C++
-    def _array_entry(self, index, value, comment, fromtype, totype):
-        pass
-
-class StdCppHeaderLanguageGenerator(CppHeaderLanguageGenerator):
-
-    def __init__(self):
-        super(StdCppHeaderLanguageGenerator, self).__init__("unsigned short", "char *", "unsigned int")
-
-class PythonLanguageGenerator(LanguageSrcGenerator):
-
-    def _boilerplate(self, lines):
-        print("#")
-        for line in lines:
-            print("# %s" % line)
-        print("#")
-
-    def _array_start(self, varname, length, defvalue, fromtype, totype):
-        if fromtype == self.TYPE_ENUM:
-            raise NotImplementedError("Enums not supported as source in Python generator")
-
-        if fromtype != self.TYPE_STRING:
-            print("%s = [" % varname)
-        else:
-            print("%s = {" % varname)
-
-    def _array_end(self, fromtype, totype):
-        if fromtype != self.TYPE_STRING:
-            print("]")
-        else:
-            print("}")
-
-    def _array_entry(self, index, value, comment, fromtype, totype):
-        if fromtype == self.TYPE_INT:
-            if value is None:
-                print("  None, # %s" % (comment))
-            elif totype == self.TYPE_INT:
-                print("  0x%x, # %s" % (value, comment))
-            elif totype == self.TYPE_ENUM:
-                print("  %s, # %s" % (value, comment))
-            else:
-                print("  \"%s\", # %s" % (value, comment))
-        else:
-            if value is None:
-                print("  \"%s\": None, # %s" % (index, comment))
-            elif totype == self.TYPE_INT:
-                print("  \"%s\": 0x%x, # %s" % (index, value, comment))
-            elif totype == self.TYPE_ENUM:
-                print("  \"%s\": %s, # %s" % (index, value, comment))
-            else:
-                print("  \"%s\": \"%s\", # %s" % (index, value, comment))
-
-class PerlLanguageGenerator(LanguageSrcGenerator):
-
-    def _boilerplate(self, lines):
-        print("#")
-        for line in lines:
-            print("# %s" % line)
-        print("#")
-
-    def _array_start(self, varname, length, defvalue, fromtype, totype):
-        if fromtype == self.TYPE_ENUN:
-            raise NotImplementedError("Enums not supported as source in Python generator")
-        if fromtype == self.TYPE_INT:
-            print("my @%s = (" % varname)
-        else:
-            print("my %%%s = (" % varname)
-
-    def _array_end(self, fromtype, totype):
-        print(");")
-
-    def _array_entry(self, index, value, comment, fromtype, totype):
-        if fromtype == self.TYPE_INT:
-            if value is None:
-                print("  undef, # %s" % (comment))
-            elif totype == self.TYPE_INT:
-                print("  0x%x, # %s" % (value, comment))
-            elif totype == self.TYPE_ENUM:
-                print("  %s, # %s" % (value, comment))
-            else:
-                print("  \"%s\", # %s" % (value, comment))
-        else:
-            if value is None:
-                print("  \"%s\", undef, # %s" % (index, comment))
-            elif totype == self.TYPE_INT:
-                print("  \"%s\", 0x%x, # %s" % (index, value, comment))
-            elif totype == self.TYPE_ENUM:
-                print("  \"%s\", 0x%x, # %s" % (index, value, comment))
-            else:
-                print("  \"%s\", \"%s\", # %s" % (index, value, comment))
-
-class JavaScriptLanguageGenerator(LanguageSrcGenerator):
-
-    def _boilerplate(self, lines):
-        print("/*")
-        for line in lines:
-            print(" * %s" % line)
-        print("*/")
-
-    def _array_start(self, varname, length, defvalue, fromtype, totype):
-        print("export default {")
-
-    def _array_end(self, fromtype, totype):
-        print("};")
-
-    def _array_entry(self, index, value, comment, fromtype, totype):
-        if value is None:
-            return
-
-        if fromtype == self.TYPE_INT:
-            fromfmt = "0x%x"
-        elif fromtype == self.TYPE_ENUM:
-            fromfmt = "%s"
-        else:
-            fromfmt = "\"%s\""
-
-        if totype == self.TYPE_INT:
-            tofmt = "0x%x"
-        elif totype == self.TYPE_ENUM:
-            tofmt = "%s"
-        else:
-            tofmt = "\"%s\""
-
-        print(("  " + fromfmt + ": " + tofmt + ", /* %s */") % (index, value, comment))
-
-class PodLanguageGenerator(LanguageDocGenerator):
-
-    def _boilerplate(self, lines):
-        print("#")
-        for line in lines:
-            print("# %s" % line)
-        print("#")
-
-    def _array_start_name_doc(self, title, subtitle, namemap):
-        print("=head1 NAME")
-        print("")
-        print("%s - %s" % (title, subtitle))
-        print("")
-        print("=head1 DESCRIPTION")
-        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, title, subtitle, codemap, namemap):
-        print("=head1 NAME")
-        print("")
-        print("%s - %s" % (title, subtitle))
-        print("")
-        print("=head1 DESCRIPTION")
-        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("")
-
-class RSTLanguageGenerator(LanguageDocGenerator):
-
-    def _boilerplate(self, lines):
-        print("..")
-        for line in lines:
-            print("   %s" % line)
-        print("")
-
-    def _array_start_name_doc(self, title, subtitle, namemap):
-        print("=" * len(title))
-        print(title)
-        print("=" * len(title))
-        print("")
-        print("-" * len(subtitle))
-        print(subtitle)
-        print("-" * len(subtitle))
-        print("")
-        print(":Manual section: 7")
-        print(":Manual group: Virtualization Support")
-        print("")
-        print("DESCRIPTION")
-        print("===========")
-        print("List of %s key code names, with corresponding key code values" % namemap)
-        print("")
-
-    def _array_start_code_doc(self, title, subtitle, codemap, namemap):
-        print("=" * len(title))
-        print(title)
-        print("=" * len(title))
-        print("")
-        print("-" * len(subtitle))
-        print(subtitle)
-        print("-" * len(subtitle))
-        print("")
-        print(":Manual section: 7")
-        print(":Manual group: Virtualization Support")
-        print("")
-        print("DESCRIPTION")
-        print("===========")
-        print("List of %s key code values, with corresponding %s key code names" % (codemap, namemap))
-        print("")
-
-    def _array_end(self):
-        print("")
-
-    def _array_name_entry(self, value, name):
-        print("* %s" % name)
-        print("")
-        print("  Key value %d (0x%x)" % (value, value))
-        print("")
-
-    def _array_code_entry(self, value, name):
-        print("* %d (0x%x)" % (value, value))
-        print("")
-        print("  Key name %s" % name)
-        print("")
-
-SRC_GENERATORS = {
-    "stdc": StdCLanguageGenerator(),
-    "stdc-header": StdCHeaderLanguageGenerator(),
-    "stdc++": StdCppLanguageGenerator(),
-    "stdc++-header": StdCppHeaderLanguageGenerator(),
-    "glib2": GLib2LanguageGenerator(),
-    "glib2-header": GLib2HeaderLanguageGenerator(),
-    "python2": PythonLanguageGenerator(),
-    "python3": PythonLanguageGenerator(),
-    "perl": PerlLanguageGenerator(),
-    "js": JavaScriptLanguageGenerator(),
-}
-DOC_GENERATORS = {
-    "pod": PodLanguageGenerator(),
-    "rst": RSTLanguageGenerator(),
-}
-
-def code_map(args):
-    database = Database()
-    database.load(args.keymaps)
-
-    cliargs = ["keymap-gen", "code-map", "--lang=%s" % args.lang]
-    if args.varname is not None:
-        cliargs.append("--varname=%s" % args.varname)
-    cliargs.extend(["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", "code-table", "--lang=%s" % args.lang]
-    if args.varname is not None:
-        cliargs.append("--varname=%s" % args.varname)
-    cliargs.extend(["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", "name-map", "--lang=%s" % args.lang]
-    if args.varname is not None:
-        cliargs.append("--varname=%s" % args.varname)
-    cliargs.extend(["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", "name-table", "--lang=%s" % args.lang]
-    if args.varname is not None:
-        cliargs.append("--varname=%s" % args.varname)
-    cliargs.extend(["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", "code-docs", "--lang=%s" % args.lang]
-    if args.title is not None:
-        cliargs.append("--title=%s" % args.title)
-    if args.subtitle is not None:
-        cliargs.append("--subtitle=%s" % args.subtitle)
-    cliargs.extend(["keymaps.csv", args.mapname])
-    DOC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs))
-
-    DOC_GENERATORS[args.lang].generate_code_docs(args.title, args.subtitle, database, args.mapname)
-
-def name_docs(args):
-    database = Database()
-    database.load(args.keymaps)
-
-
-    cliargs = ["keymap-gen", "name-docs", "--lang=%s" % args.lang]
-    if args.title is not None:
-        cliargs.append("--title=%s" % args.title)
-    if args.subtitle is not None:
-        cliargs.append("--subtitle=%s" % args.subtitle)
-    cliargs.extend(["keymaps.csv", args.mapname])
-    DOC_GENERATORS[args.lang].generate_header(database, " ".join(cliargs))
-
-    DOC_GENERATORS[args.lang].generate_name_docs(args.title, args.subtitle, 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()
-
-    subparsers = parser.add_subparsers(help="sub-command help")
-
-    codemapparser = subparsers.add_parser("code-map", help="Generate a mapping between code tables")
-    codemapparser.add_argument("--varname", default=None, help="Data variable name")
-    codemapparser.add_argument("--lang", default="stdc",
-                        help="Output language (%s)" % (
-                            ",".join(SRC_GENERATORS.keys())))
-    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("--lang", default="stdc",
-                        help="Output language (%s)" % (
-                            ",".join(SRC_GENERATORS.keys())))
-    codetableparser.add_argument("--varname", default=None, help="Data variable name")
-    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("--lang", default="stdc",
-                        help="Output language (%s)" % (
-                            ",".join(SRC_GENERATORS.keys())))
-    namemapparser.add_argument("--varname", default=None, help="Data variable name")
-    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("--lang", default="stdc",
-                        help="Output language, (%s)" % (
-                            ",".join(SRC_GENERATORS.keys())))
-    nametableparser.add_argument("--varname", default=None, help="Data variable name")
-    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("--lang", default="pod",
-                        help="Output language (%s)" % (
-                            ",".join(DOC_GENERATORS.keys())))
-    codedocsparser.add_argument("--title", default=None, help="Document title")
-    codedocsparser.add_argument("--subtitle", default=None, help="Document subtitle")
-    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("--lang", default="pod",
-                        help="Output language (%s)" % (
-                            ",".join(DOC_GENERATORS.keys())))
-    namedocsparser.add_argument("--title", default=None, help="Document title")
-    namedocsparser.add_argument("--subtitle", default=None, help="Document subtitle")
-    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()
-- 
2.39.2






More information about the pve-devel mailing list