Handle maps where 0x0 is a valid key

With OS-X / ADB keycodes 0x0 refers to key 'A', so cannot be
used as the default in the array. We must use 0xff instead and
thus explicitly fill every array entry with 0xff if no mapping
is available.

To handle this for enum based source maps, we need to use the
magic syntax

   [0 .... max] = value,

to set the default value in all elements, and then override
it afterwards for mappings which are known.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
diff --git a/data/keymaps.csv b/data/keymaps.csv
index 9b63d75..d0367c3 100644
--- a/data/keymaps.csv
+++ b/data/keymaps.csv
@@ -1,5 +1,5 @@
 "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,,,,,,,,,,,,,,,unmapped,,
+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
diff --git a/tools/keymap-gen b/tools/keymap-gen
index f3a8634..34de305 100755
--- a/tools/keymap-gen
+++ b/tools/keymap-gen
@@ -320,7 +320,7 @@
     TYPE_STRING = "string"
     TYPE_ENUM = "enum"
 
-    def _array_start(self, varname, length, fromtype, totype):
+    def _array_start(self, varname, length, defvalue, fromtype, totype):
         raise NotImplementedError()
 
     def _array_end(self, fromtype, totype):
@@ -367,14 +367,18 @@
         else:
             keymax = len(keys)
 
-        self._array_start(varname, keymax, fromtype, totype)
+        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, None)
+                dst = fromlinux.get(linux, defvalue)
 
             comment = "%s -> %s -> %s" % (self._label(database, frommapname, src, linux),
                                           self._label(database, Database.MAP_LINUX, linux, linux),
@@ -401,11 +405,12 @@
         else:
             totype = self.TYPE_INT
 
-        self._array_start(varname, len(keys), self.TYPE_INT, totype)
+        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, None)
+            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)
@@ -434,7 +439,7 @@
         else:
             fromtype = self.TYPE_STRING
 
-        self._array_start(varname, len(keys), fromtype, self.TYPE_STRING)
+        self._array_start(varname, len(keys), None, fromtype, self.TYPE_STRING)
 
         for src in keys:
             linux = tolinux.get(src, None)
@@ -461,7 +466,7 @@
         if varname is None:
             varname = "name_table_%s" % mapname
 
-        self._array_start(varname, len(keys), self.TYPE_INT, self.TYPE_STRING)
+        self._array_start(varname, len(keys), None, self.TYPE_INT, self.TYPE_STRING)
 
         for i in range(len(keys)):
             key = keys[i]
@@ -553,7 +558,7 @@
             print(" * %s" % line)
         print("*/")
 
-    def _array_start(self, varname, length, fromtype, totype):
+    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):
@@ -567,6 +572,18 @@
             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 unsigned int %s_len = sizeof(%s)/sizeof(%s[0]);" %
@@ -596,7 +613,7 @@
 
 class CppLanguageGenerator(CLanguageGenerator):
 
-    def _array_start(self, varname, length, fromtype, totype):
+    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
@@ -648,7 +665,7 @@
             print("# %s" % line)
         print("#")
 
-    def _array_start(self, varname, length, fromtype, totype):
+    def _array_start(self, varname, length, defvalue, fromtype, totype):
         if fromtype == self.TYPE_ENUM:
             raise NotImplementedError("Enums not supported as source in Python generator")
 
@@ -691,7 +708,7 @@
             print("# %s" % line)
         print("#")
 
-    def _array_start(self, varname, length, fromtype, totype):
+    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:
@@ -730,7 +747,7 @@
             print(" * %s" % line)
         print("*/")
 
-    def _array_start(self, varname, length, fromtype, totype):
+    def _array_start(self, varname, length, defvalue, fromtype, totype):
         print("export default {")
 
     def _array_end(self, fromtype, totype):