Commit 27fe8d1657f329068c574f1bc869dc725708f3af

Dan Nicholson 2009-01-14T07:35:10

Add makekeys for creating keysym hash tables The makekeys utility is used to generate the keysym hash tables during the build. We try to detect a build machine native compiler so the tables can be generated when cross compiling.

diff --git a/Makefile.am b/Makefile.am
index 0222143..308357b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,5 @@
+SUBDIRS = src
+
 EXTRA_DIST = ChangeLog
 
 MAINTAINERCLEANFILES = ChangeLog
diff --git a/configure.ac b/configure.ac
index c0137f4..90eec9e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,14 +27,36 @@ AM_INIT_AUTOMAKE([dist-bzip2 foreign])
 AM_MAINTAINER_MODE
 
 AC_PROG_LIBTOOL
+AC_PROG_CC
 
-# Require xorg-macros version 1.1.0 or newer for XORG_WITH_LINT macro
+m4_ifndef([PKG_PROG_PKG_CONFIG],
+    [m4_fatal([Could not locate the pkg-config autoconf macros.
+    These are usually located in /usr/share/aclocal/pkg.m4. If your
+    macros are in a different location, try setting the environment
+    variable ACLOCAL="aclocal -I/other/macro/dir" before running
+    autoreconf/autogen.sh.])])
+PKG_PROG_PKG_CONFIG
+
+dnl Build native compiler needed for makekeys
+AC_ARG_VAR([CC_FOR_BUILD], [Build native C compiler program])
+if test "x$CC_FOR_BUILD" != x; then
+    if test "$cross_compiling" != no; then
+        AC_PATH_PROGS([CC_FOR_BUILD], [gcc cc], [cc])
+    else
+        CC_FOR_BUILD="$CC"
+    fi
+fi
+
+PKG_CHECK_MODULES([X11], [xproto])
+
+# Require xorg-macros version 1.2.0 or newer for XORG_CHANGELOG macro
 m4_ifndef([XORG_MACROS_VERSION],
-    [m4_fatal([must install xorg-macros 1.1 or later before running autoconf/autogen])])
-XORG_MACROS_VERSION([1.1])
+    [m4_fatal([must install xorg-macros before running autoconf/autogen.sh])])
+XORG_MACROS_VERSION([1.2.0])
 XORG_RELEASE_VERSION
 XORG_CHANGELOG
 
 AC_OUTPUT([
 Makefile
+src/Makefile
 ])
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..2bdb5e0
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1 @@
+makekeys
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..53f1911
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,3 @@
+noinst_PROGRAMS = makekeys
+makekeys_CFLAGS = $(X11_CFLAGS)
+makekeys: CC = $(CC_FOR_BUILD)
diff --git a/src/makekeys.c b/src/makekeys.c
new file mode 100644
index 0000000..eacd180
--- /dev/null
+++ b/src/makekeys.c
@@ -0,0 +1,274 @@
+/* $Xorg: makekeys.c,v 1.5 2001/02/09 02:03:40 $ */
+/* $XdotOrg: lib/X11/src/util/makekeys.c,v 1.5 2005-07-03 07:00:56 daniels Exp $ */
+/*
+
+Copyright 1990, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: $ */
+
+/* Constructs hash tables for XStringToKeysym and XKeysymToString. */
+
+#include <X11/X.h>
+#include <X11/Xos.h>
+#include <X11/keysymdef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(macII) && !defined(__STDC__)  /* stdlib.h fails to define these */
+char *malloc();
+#endif /* macII */
+
+typedef unsigned long Signature;
+
+#define KTNUM 4000
+
+static struct info {
+    char	*name;
+    KeySym	val;
+} info[KTNUM];
+
+#define MIN_REHASH 15
+#define MATCHES 10
+
+static char tab[KTNUM];
+static unsigned short offsets[KTNUM];
+static unsigned short indexes[KTNUM];
+static KeySym values[KTNUM];
+static char buf[1024];
+
+int
+main(int argc, char *argv[])
+{
+    int ksnum = 0;
+    int max_rehash;
+    Signature sig;
+    register int i, j, k, z;
+    register char *name;
+    register char c;
+    int first;
+    int best_max_rehash;
+    int best_z = 0;
+    int num_found;
+    KeySym val;
+    char key[128];
+    char alias[128];
+
+
+    while (fgets(buf, sizeof(buf), stdin)) {
+	i = sscanf(buf, "#define XK_%127s 0x%lx", key, &info[ksnum].val);
+	if (i != 2) {
+	    i = sscanf(buf, "#define XK_%127s XK_%127s", key, alias);
+	    if (i != 2)
+		continue;
+	    for (i = ksnum - 1; i >= 0; i--) {
+		if (strcmp(info[i].name, alias) == 0) {
+		    info[ksnum].val = info[i].val;
+		    break;
+		}
+	    }
+	    if (i < 0) {  /* Didn't find a match */
+		fprintf(stderr,
+		    "can't find matching definition %s for keysym %s\n",
+		    alias, key);
+		continue;
+	    }
+	}
+	if (info[ksnum].val == XK_VoidSymbol)
+	    info[ksnum].val = 0;
+	if (info[ksnum].val > 0x1fffffff) {
+	    fprintf(stderr,
+		    "ignoring illegal keysym (%s), remove it from .h file!\n",
+		    key);
+	    continue;
+	}
+	name = malloc((unsigned)strlen(key)+1);
+	if (!name) {
+	    fprintf(stderr, "makekeys: out of memory!\n");
+	    exit(1);
+	}
+	(void)strcpy(name, key);
+	info[ksnum].name = name;
+	ksnum++;
+	if (ksnum == KTNUM) {
+	    fprintf(stderr, "makekeys: too many keysyms!\n");
+	    exit(1);
+	}
+    }
+
+    printf("/* This file is generated from keysymdef.h. */\n");
+    printf("/* Do not edit. */\n");
+    printf("\n");
+
+    best_max_rehash = ksnum;
+    num_found = 0;
+    for (z = ksnum; z < KTNUM; z++) {
+	max_rehash = 0;
+	for (name = tab, i = z; --i >= 0;)
+		*name++ = 0;
+	for (i = 0; i < ksnum; i++) {
+	    name = info[i].name;
+	    sig = 0;
+	    while ((c = *name++))
+		sig = (sig << 1) + c;
+	    first = j = sig % z;
+	    for (k = 0; tab[j]; k++) {
+		j += first + 1;
+		if (j >= z)
+		    j -= z;
+		if (j == first)
+		    goto next1;
+	    }
+	    tab[j] = 1;
+	    if (k > max_rehash)
+		max_rehash = k;
+	}
+	if (max_rehash < MIN_REHASH) {
+	    if (max_rehash < best_max_rehash) {
+		best_max_rehash = max_rehash;
+		best_z = z;
+	    }
+	    num_found++;
+	    if (num_found >= MATCHES)
+		break;
+	}
+next1:	;
+    }
+
+    z = best_z;
+    printf("#ifdef NEEDKTABLE\n");
+    printf("const unsigned char _XkeyTable[] = {\n");
+    printf("0,\n");
+    k = 1;
+    for (i = 0; i < ksnum; i++) {
+	name = info[i].name;
+	sig = 0;
+	while ((c = *name++))
+	    sig = (sig << 1) + c;
+	first = j = sig % z;
+	while (offsets[j]) {
+	    j += first + 1;
+	    if (j >= z)
+		j -= z;
+	}
+	offsets[j] = k;
+	indexes[i] = k;
+	val = info[i].val;
+	printf("0x%.2lx, 0x%.2lx, 0x%.2lx, 0x%.2lx, 0x%.2lx, 0x%.2lx, ",
+	       (sig >> 8) & 0xff, sig & 0xff,
+	       (val >> 24) & 0xff, (val >> 16) & 0xff,
+	       (val >> 8) & 0xff, val & 0xff);
+	for (name = info[i].name, k += 7; (c = *name++); k++)
+	    printf("'%c',", c);
+	printf((i == (ksnum-1)) ? "0\n" : "0,\n");
+    }
+    printf("};\n");
+    printf("\n");
+    printf("#define KTABLESIZE %d\n", z);
+    printf("#define KMAXHASH %d\n", best_max_rehash + 1);
+    printf("\n");
+    printf("static const unsigned short hashString[KTABLESIZE] = {\n");
+    for (i = 0; i < z;) {
+	printf("0x%.4x", offsets[i]);
+	i++;
+	if (i == z)
+	    break;
+	printf((i & 7) ? ", " : ",\n");
+    }
+    printf("\n");
+    printf("};\n");
+    printf("#endif /* NEEDKTABLE */\n");
+
+    best_max_rehash = ksnum;
+    num_found = 0;
+    for (z = ksnum; z < KTNUM; z++) {
+	max_rehash = 0;
+	for (name = tab, i = z; --i >= 0;)
+		*name++ = 0;
+	for (i = 0; i < ksnum; i++) {
+	    val = info[i].val;
+	    first = j = val % z;
+	    for (k = 0; tab[j]; k++) {
+		if (values[j] == val)
+		    goto skip1;
+		j += first + 1;
+		if (j >= z)
+		    j -= z;
+		if (j == first)
+		    goto next2;
+	    }
+	    tab[j] = 1;
+	    values[j] = val;
+	    if (k > max_rehash)
+		max_rehash = k;
+skip1:	;
+	}
+	if (max_rehash < MIN_REHASH) {
+	    if (max_rehash < best_max_rehash) {
+		best_max_rehash = max_rehash;
+		best_z = z;
+	    }
+	    num_found++;
+	    if (num_found >= MATCHES)
+		break;
+	}
+next2:	;
+    }
+
+    z = best_z;
+    for (i = z; --i >= 0;)
+	offsets[i] = 0;
+    for (i = 0; i < ksnum; i++) {
+	val = info[i].val;
+	first = j = val % z;
+	while (offsets[j]) {
+	    if (values[j] == val)
+		goto skip2;
+	    j += first + 1;
+	    if (j >= z)
+		j -= z;
+	}
+	offsets[j] = indexes[i] + 2;
+	values[j] = val;
+skip2:	;
+    }
+    printf("\n");
+    printf("#ifdef NEEDVTABLE\n");
+    printf("#define VTABLESIZE %d\n", z);
+    printf("#define VMAXHASH %d\n", best_max_rehash + 1);
+    printf("\n");
+    printf("static const unsigned short hashKeysym[VTABLESIZE] = {\n");
+    for (i = 0; i < z;) {
+	printf("0x%.4x", offsets[i]);
+	i++;
+	if (i == z)
+	    break;
+	printf((i & 7) ? ", " : ",\n");
+    }
+    printf("\n");
+    printf("};\n");
+    printf("#endif /* NEEDVTABLE */\n");
+
+    exit(0);
+}