compose: Generate endian-dependent compact Compose data
authorSimon McVittie <smcv@debian.org>
Mon, 30 Aug 2021 09:13:33 +0000 (10:13 +0100)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 2 Sep 2021 23:59:41 +0000 (19:59 -0400)
The GtkComposeTable cache is always in big-endian format and is
byteswapped on load for the more common little-endian CPUs, but
init_builtin_table() in GtkIMContextSimple can't byteswap the built-in
data without copying it, which is undesirable. Pregenerate both big-
and little-endian compose data, and compile the correct flavour into
each build of GTK. This fixes failure of the composetable test when
building for a big-endian architecture such as s390x and (traditional,
big-endian) powerpc.

Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/4217
Signed-off-by: Simon McVittie <smcv@debian.org>
gtk/compose/compose-parse.c
gtk/compose/sequences [deleted file]
gtk/compose/sequences-big-endian [new file with mode: 0644]
gtk/compose/sequences-little-endian [new file with mode: 0644]
gtk/gen-gtk-gresources-xml.py
gtk/meson.build

index 7a3d511132d7e0fddd8d90149aeb311ac16f90c1..a1ec09d00d0964575d262b5ccc66106f773b5041 100644 (file)
@@ -7,7 +7,7 @@
  * character data, and definitions for the builtin compose table of GTK.
  * Run it like this:
  *
- *   compose-parse Compose sequences chars gtkcomposedata.h
+ *   compose-parse Compose sequences-little-endian sequences-big-endian chars gtkcomposedata.h
  *
  * The GTK build expects the output files to be in the source tree, in
  * the gtk/compose directory.
 int
 main (int argc, char *argv[])
 {
+  const guint16 *sequences_le;
+  const guint16 *sequences_be;
+  guint16 *other_sequences;
   GtkComposeTable *table;
   GError *error = NULL;
   GString *str;
+  gsize i;
 
   setlocale (LC_ALL, "");
 
   if (argc < 5)
     {
-      g_print ("Usage: compose-parse INPUT OUTPUT1 OUTPUT2 OUTPUT3\n");
+      g_print ("Usage: compose-parse INPUT SEQUENCES-LE SEQUENCES-BE CHARS HEADER\n");
       exit (1);
     }
 
@@ -31,11 +35,26 @@ main (int argc, char *argv[])
   if (!table)
     g_error ("Failed to parse %s", argv[1]);
 
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+  sequences_le = other_sequences = g_new0 (guint16, table->data_size);
+  sequences_be = (const guint16 *) table->data;
+#else
+  sequences_le = (const guint16 *) table->data;
+  sequences_be = other_sequences = g_new0 (guint16, table->data_size);
+#endif
+
+  for (i = 0; i < table->data_size; i++)
+    other_sequences[i] = GUINT16_SWAP_LE_BE (table->data[i]);
+
+  /* data_size is the size in guint16 */
+  if (!g_file_set_contents (argv[2], (char *) sequences_le, 2 * table->data_size, &error))
+    g_error ("%s", error->message);
+
   /* data_size is the size in guint16 */
-  if (!g_file_set_contents (argv[2], (char *)table->data, 2 * table->data_size, &error))
+  if (!g_file_set_contents (argv[3], (char *) sequences_be, 2 * table->data_size, &error))
     g_error ("%s", error->message);
 
-  if (!g_file_set_contents (argv[3], table->char_data, table->n_chars + 1, &error))
+  if (!g_file_set_contents (argv[4], table->char_data, table->n_chars + 1, &error))
     g_error ("%s", error->message);
 
   str = g_string_new ("");
@@ -55,10 +74,11 @@ main (int argc, char *argv[])
                    "\n"
                    "#endif\n");
 
-  if (!g_file_set_contents (argv[4], str->str, str->len, &error))
+  if (!g_file_set_contents (argv[5], str->str, str->len, &error))
     g_error ("%s", error->message);
 
   g_string_free (str, TRUE);
+  g_free (other_sequences);
 
   return 0;
 }
diff --git a/gtk/compose/sequences b/gtk/compose/sequences
deleted file mode 100644 (file)
index 39984d4..0000000
Binary files a/gtk/compose/sequences and /dev/null differ
diff --git a/gtk/compose/sequences-big-endian b/gtk/compose/sequences-big-endian
new file mode 100644 (file)
index 0000000..5165779
Binary files /dev/null and b/gtk/compose/sequences-big-endian differ
diff --git a/gtk/compose/sequences-little-endian b/gtk/compose/sequences-little-endian
new file mode 100644 (file)
index 0000000..39984d4
Binary files /dev/null and b/gtk/compose/sequences-little-endian differ
index 8a8da4254e3cb9b95d23e8b47a51a2b144616d84..81c06637bc1f0e0e1d506b3d40ea17260dadca9e 100644 (file)
@@ -21,6 +21,7 @@ def replace_if_changed(new, old):
     os.remove(new)
 
 srcdir = sys.argv[1]
+endian = sys.argv[2]
 
 xml = '''<?xml version='1.0' encoding='UTF-8'?>
 <gresources>
@@ -84,13 +85,13 @@ for f in get_files('inspector', '.ui'):
 xml += '''
     <file>inspector/inspector.css</file>
     <file>emoji/en.data</file>
-    <file>compose/sequences</file>
+    <file alias="compose/sequences">compose/sequences-{0}-endian</file>
     <file>compose/chars</file>
   </gresource>
-</gresources>'''
+</gresources>'''.format(endian)
 
-if len(sys.argv) > 2:
-  outfile = sys.argv[2]
+if len(sys.argv) > 3:
+  outfile = sys.argv[3]
   tmpfile = outfile + '~'
   with open(tmpfile, 'w') as f:
     f.write(xml)
index 18fbe6ac61455ee7ca8cf96f5fa04cc7bd93d68b..b123e062b39f0835800da255c080c6631ed7a0d8 100644 (file)
@@ -835,6 +835,7 @@ gtk_gresources_xml = configure_file(output: 'gtk.gresources.xml',
   command: [
     gen_gtk_gresources_xml,
     meson.current_source_dir(),
+    host_machine.endian(),
     '@OUTPUT@'
   ],
 )