Edit

kc3-lang/libxkbcommon/makekeys/makekeys.c

Branch :

  • Show log

    Commit

  • Author : Daniel Stone
    Date : 2012-07-17 10:20:15
    Hash : 9308a460
    Message : Run source tree through uncrustify .uncrustify.cfg committed for future reference also, but had to manually fix up a few things: it really likes justifying struct initialisers. Signed-off-by: Daniel Stone <daniel@fooishbar.org>

  • makekeys/makekeys.c
  • /*
     *
     * 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.
     *
     */
    
    /*
     * Constructs hash tables for xkb_keysym_to_string and
     * xkb_string_from_keysym.
     */
    
    #include "xkbcommon/xkbcommon.h"
    
    #include <inttypes.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef uint32_t Signature;
    
    #define KTNUM 4000
    
    static struct info {
        char        *name;
        xkb_keysym_t 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 xkb_keysym_t values[KTNUM];
    static int ksnum = 0;
    
    static int
    parse_line(const char *buf, char *key, xkb_keysym_t *val, char *prefix)
    {
        int i;
        char alias[128];
    
        /* See if we can catch a straight XK_foo 0x1234-style definition first;
         * the trickery around tmp is to account for prefices. */
        i = sscanf(buf, "#define %127s 0x%" SCNx32, key, val);
        if (i == 2 && strncmp(key, "XKB_KEY_", 8) == 0) {
            prefix[0] = '\0';
            memmove(key, key + 8, strlen(key + 8) + 1);
            return 1;
        }
    
        i = sscanf(buf, "#define %127s %127s", key, alias);
        if (i == 2)
            fprintf(stderr, "can't parse keysym definition: %s", buf);
    
        return 0;
    }
    
    int
    main(int argc, char *argv[])
    {
        FILE *fptr;
        int max_rehash;
        Signature sig;
        int i, j, k, l, z;
        char *name;
        char c;
        int first;
        int best_max_rehash;
        int best_z = 0;
        int num_found;
        xkb_keysym_t val;
        char key[128], prefix[128];
        char buf[1024];
    
        for (l = 1; l < argc; l++) {
            fptr = fopen(argv[l], "r");
            if (!fptr) {
                fprintf(stderr, "couldn't open %s\n", argv[l]);
                continue;
            }
    
            while (fgets(buf, sizeof(buf), fptr)) {
                if (!parse_line(buf, key, &val, prefix))
                    continue;
    
                if (val == XKB_KEY_VoidSymbol)
                    val = 0;
                if (val > 0x1fffffff) {
                    fprintf(stderr, "ignoring illegal keysym (%s, %" PRIx32 ")\n",
                            key,
                            val);
                    continue;
                }
    
                name = malloc(strlen(prefix) + strlen(key) + 1);
                if (!name) {
                    fprintf(stderr, "makekeys: out of memory!\n");
                    exit(1);
                }
                sprintf(name, "%s%s", prefix, key);
                info[ksnum].name = name;
                info[ksnum].val = val;
                ksnum++;
                if (ksnum == KTNUM) {
                    fprintf(stderr, "makekeys: too many keysyms!\n");
                    exit(1);
                }
            }
    
            fclose(fptr);
        }
    
        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("#ifndef KS_TABLES_H\n");
        printf("#define KS_TABLES_H\n\n");
        printf("static const unsigned char _XkeyTable[] = {\n");
        if (z == 0) {
            fprintf(stderr, "makekeys: failed to find small enough hash!\n"
                    "Try increasing KTNUM in makekeys.c\n");
            exit(1);
        }
        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%.2" PRIx32 ", 0x%.2" PRIx32 ", 0x%.2" PRIx32 ", "
                   "0x%.2" PRIx32 ", 0x%.2" PRIx32 ", 0x%.2" PRIx32 ", ",
                   (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");
    
        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;
        if (z == 0) {
            fprintf(stderr, "makekeys: failed to find small enough hash!\n"
                    "Try increasing KTNUM in makekeys.c\n");
            exit(1);
        }
        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("#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("\n#endif /* KS_TABLES_H */\n");
    
        for (i = 0; i < ksnum; i++)
            free(info[i].name);
    
        exit(0);
    }