makekeys.c revision 47f86ac1
1/* 2 3Copyright 1990, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29/* Constructs hash tables for XStringToKeysym and XKeysymToString. */ 30 31#include <X11/X.h> 32#include <X11/Xos.h> 33#include <X11/keysymdef.h> 34#include <stdio.h> 35#include <stdlib.h> 36 37typedef unsigned long Signature; 38 39#define KTNUM 4000 40 41static struct info { 42 char *name; 43 KeySym val; 44} info[KTNUM]; 45 46#define MIN_REHASH 15 47#define MATCHES 10 48 49static char tab[KTNUM]; 50static unsigned short offsets[KTNUM]; 51static unsigned short indexes[KTNUM]; 52static KeySym values[KTNUM]; 53static char buf[1024]; 54static int ksnum = 0; 55 56static int 57parse_line(const char *buf, char *key, KeySym *val, char *prefix) 58{ 59 int i; 60 char alias[128]; 61 char *tmp, *tmpa; 62 63 /* See if we can catch a straight XK_foo 0x1234-style definition first; 64 * the trickery around tmp is to account for prefices. */ 65 i = sscanf(buf, "#define %127s 0x%lx", key, val); 66 if (i == 2 && (tmp = strstr(key, "XK_"))) { 67 memcpy(prefix, key, tmp - key); 68 prefix[tmp - key] = '\0'; 69 tmp += 3; 70 memmove(key, tmp, strlen(tmp) + 1); 71 return 1; 72 } 73 74 /* Now try to catch alias (XK_foo XK_bar) definitions, and resolve them 75 * immediately: if the target is in the form XF86XK_foo, we need to 76 * canonicalise this to XF86foo before we do the lookup. */ 77 i = sscanf(buf, "#define %127s %127s", key, alias); 78 if (i == 2 && (tmp = strstr(key, "XK_")) && (tmpa = strstr(alias, "XK_"))) { 79 memcpy(prefix, key, tmp - key); 80 prefix[tmp - key] = '\0'; 81 tmp += 3; 82 memmove(key, tmp, strlen(tmp) + 1); 83 memmove(tmpa, tmpa + 3, strlen(tmpa + 3) + 1); 84 85 for (i = ksnum - 1; i >= 0; i--) { 86 if (strcmp(info[i].name, alias) == 0) { 87 *val = info[i].val; 88 return 1; 89 } 90 } 91 92 fprintf(stderr, "can't find matching definition %s for keysym %s%s\n", 93 alias, prefix, key); 94 } 95 96 return 0; 97} 98 99int 100main(int argc, char *argv[]) 101{ 102 int max_rehash; 103 Signature sig; 104 int i, j, k, l, z; 105 FILE *fptr; 106 char *name; 107 char c; 108 int first; 109 int best_max_rehash; 110 int best_z = 0; 111 int num_found; 112 KeySym val; 113 char key[128], prefix[128]; 114 115 for (l = 1; l < argc; l++) { 116 fptr = fopen(argv[l], "r"); 117 if (!fptr) { 118 fprintf(stderr, "couldn't open %s\n", argv[l]); 119 continue; 120 } 121 122 while (fgets(buf, sizeof(buf), fptr)) { 123 if (!parse_line(buf, key, &val, prefix)) 124 continue; 125 126 if (val == XK_VoidSymbol) 127 val = 0; 128 if (val > 0x1fffffff) { 129 fprintf(stderr, "ignoring illegal keysym (%s, %lx)\n", key, 130 val); 131 continue; 132 } 133 134 name = malloc(strlen(prefix) + strlen(key) + 1); 135 if (!name) { 136 fprintf(stderr, "makekeys: out of memory!\n"); 137 exit(1); 138 } 139 sprintf(name, "%s%s", prefix, key); 140 info[ksnum].name = name; 141 info[ksnum].val = val; 142 ksnum++; 143 if (ksnum == KTNUM) { 144 fprintf(stderr, "makekeys: too many keysyms!\n"); 145 exit(1); 146 } 147 } 148 149 fclose(fptr); 150 } 151 152 printf("/* This file is generated from keysymdef.h. */\n"); 153 printf("/* Do not edit. */\n"); 154 printf("\n"); 155 156 best_max_rehash = ksnum; 157 num_found = 0; 158 for (z = ksnum; z < KTNUM; z++) { 159 max_rehash = 0; 160 for (name = tab, i = z; --i >= 0;) 161 *name++ = 0; 162 for (i = 0; i < ksnum; i++) { 163 name = info[i].name; 164 sig = 0; 165 while ((c = *name++)) 166 sig = (sig << 1) + c; 167 first = j = sig % z; 168 for (k = 0; tab[j]; k++) { 169 j += first + 1; 170 if (j >= z) 171 j -= z; 172 if (j == first) 173 goto next1; 174 } 175 tab[j] = 1; 176 if (k > max_rehash) 177 max_rehash = k; 178 } 179 if (max_rehash < MIN_REHASH) { 180 if (max_rehash < best_max_rehash) { 181 best_max_rehash = max_rehash; 182 best_z = z; 183 } 184 num_found++; 185 if (num_found >= MATCHES) 186 break; 187 } 188next1: ; 189 } 190 191 z = best_z; 192 if (z == 0) { 193 fprintf(stderr, "makekeys: failed to find small enough hash!\n" 194 "Try increasing KTNUM in makekeys.c\n"); 195 exit(1); 196 } 197 printf("#ifdef NEEDKTABLE\n"); 198 printf("const unsigned char _XkeyTable[] = {\n"); 199 printf("0,\n"); 200 k = 1; 201 for (i = 0; i < ksnum; i++) { 202 name = info[i].name; 203 sig = 0; 204 while ((c = *name++)) 205 sig = (sig << 1) + c; 206 first = j = sig % z; 207 while (offsets[j]) { 208 j += first + 1; 209 if (j >= z) 210 j -= z; 211 } 212 offsets[j] = k; 213 indexes[i] = k; 214 val = info[i].val; 215 printf("0x%.2lx, 0x%.2lx, 0x%.2lx, 0x%.2lx, 0x%.2lx, 0x%.2lx, ", 216 (sig >> 8) & 0xff, sig & 0xff, 217 (val >> 24) & 0xff, (val >> 16) & 0xff, 218 (val >> 8) & 0xff, val & 0xff); 219 for (name = info[i].name, k += 7; (c = *name++); k++) 220 printf("'%c',", c); 221 printf((i == (ksnum-1)) ? "0\n" : "0,\n"); 222 } 223 printf("};\n"); 224 printf("\n"); 225 printf("#define KTABLESIZE %d\n", z); 226 printf("#define KMAXHASH %d\n", best_max_rehash + 1); 227 printf("\n"); 228 printf("static const unsigned short hashString[KTABLESIZE] = {\n"); 229 for (i = 0; i < z;) { 230 printf("0x%.4x", offsets[i]); 231 i++; 232 if (i == z) 233 break; 234 printf((i & 7) ? ", " : ",\n"); 235 } 236 printf("\n"); 237 printf("};\n"); 238 printf("#endif /* NEEDKTABLE */\n"); 239 240 best_max_rehash = ksnum; 241 num_found = 0; 242 for (z = ksnum; z < KTNUM; z++) { 243 max_rehash = 0; 244 for (name = tab, i = z; --i >= 0;) 245 *name++ = 0; 246 for (i = 0; i < ksnum; i++) { 247 val = info[i].val; 248 first = j = val % z; 249 for (k = 0; tab[j]; k++) { 250 if (values[j] == val) 251 goto skip1; 252 j += first + 1; 253 if (j >= z) 254 j -= z; 255 if (j == first) 256 goto next2; 257 } 258 tab[j] = 1; 259 values[j] = val; 260 if (k > max_rehash) 261 max_rehash = k; 262skip1: ; 263 } 264 if (max_rehash < MIN_REHASH) { 265 if (max_rehash < best_max_rehash) { 266 best_max_rehash = max_rehash; 267 best_z = z; 268 } 269 num_found++; 270 if (num_found >= MATCHES) 271 break; 272 } 273next2: ; 274 } 275 276 z = best_z; 277 if (z == 0) { 278 fprintf(stderr, "makekeys: failed to find small enough hash!\n" 279 "Try increasing KTNUM in makekeys.c\n"); 280 exit(1); 281 } 282 for (i = z; --i >= 0;) 283 offsets[i] = 0; 284 for (i = 0; i < ksnum; i++) { 285 val = info[i].val; 286 first = j = val % z; 287 while (offsets[j]) { 288 if (values[j] == val) 289 goto skip2; 290 j += first + 1; 291 if (j >= z) 292 j -= z; 293 } 294 offsets[j] = indexes[i] + 2; 295 values[j] = val; 296skip2: ; 297 } 298 printf("\n"); 299 printf("#ifdef NEEDVTABLE\n"); 300 printf("#define VTABLESIZE %d\n", z); 301 printf("#define VMAXHASH %d\n", best_max_rehash + 1); 302 printf("\n"); 303 printf("static const unsigned short hashKeysym[VTABLESIZE] = {\n"); 304 for (i = 0; i < z;) { 305 printf("0x%.4x", offsets[i]); 306 i++; 307 if (i == z) 308 break; 309 printf((i & 7) ? ", " : ",\n"); 310 } 311 printf("\n"); 312 printf("};\n"); 313 printf("#endif /* NEEDVTABLE */\n"); 314 315 exit(0); 316} 317