root/drivers/accessibility/speakup/utils.h
/* SPDX-License-Identifier: GPL-2.0+ */
/* utils.h
 * originally written by: Kirk Reiser.
 *
 ** Copyright (C) 2002  Kirk Reiser.
 *  Copyright (C) 2003  David Borowski.
 */

#include <stdio.h>

#define MAXKEYS 512
#define MAXKEYVAL 160
#define HASHSIZE 101
#define is_shift -3
#define is_spk -2
#define is_input -1

struct st_key {
        char *name;
        struct st_key *next;
        int value, shift;
};

struct st_key key_table[MAXKEYS];
struct st_key *extra_keys = key_table+HASHSIZE;
char *def_name, *def_val;
FILE *infile;
int lc;

char filename[256];

static inline void open_input(const char *dir_name, const char *name)
{
        if (dir_name)
                snprintf(filename, sizeof(filename), "%s/%s", dir_name, name);
        else
                snprintf(filename, sizeof(filename), "%s", name);
        infile = fopen(filename, "r");
        if (infile == 0) {
                fprintf(stderr, "can't open %s\n", filename);
                exit(1);
        }
        lc = 0;
}

static inline int oops(const char *msg, const char *info)
{
        if (info == NULL)
                info = "";
        fprintf(stderr, "error: file %s line %d\n", filename, lc);
        fprintf(stderr, "%s %s\n", msg, info);
        exit(1);
}

static inline struct st_key *hash_name(char *name)
{
        unsigned char *pn = (unsigned char *)name;
        int hash = 0;

        while (*pn) {
                hash = (hash * 17) & 0xfffffff;
                if (isupper(*pn))
                        *pn = tolower(*pn);
                hash += (int)*pn;
                pn++;
        }
        hash %= HASHSIZE;
        return &key_table[hash];
}

static inline struct st_key *find_key(char *name)
{
        struct st_key *this = hash_name(name);

        while (this) {
                if (this->name && !strcmp(name, this->name))
                        return this;
                this = this->next;
        }
        return this;
}

static inline struct st_key *add_key(char *name, int value, int shift)
{
        struct st_key *this = hash_name(name);

        if (extra_keys-key_table >= MAXKEYS)
                oops("out of key table space, enlarge MAXKEYS", NULL);
        if (this->name != NULL) {
                while (this->next) {
                        if (!strcmp(name, this->name))
                                oops("attempt to add duplicate key", name);
                        this = this->next;
                }
                this->next = extra_keys++;
                this = this->next;
        }
        this->name = strdup(name);
        this->value = value;
        this->shift = shift;
        return this;
}