162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* genmap.c 362306a36Sopenharmony_ci * originally written by: Kirk Reiser. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci ** Copyright (C) 2002 Kirk Reiser. 662306a36Sopenharmony_ci * Copyright (C) 2003 David Borowski. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <stdlib.h> 1062306a36Sopenharmony_ci#include <stdio.h> 1162306a36Sopenharmony_ci#include <libgen.h> 1262306a36Sopenharmony_ci#include <string.h> 1362306a36Sopenharmony_ci#include <linux/version.h> 1462306a36Sopenharmony_ci#include <ctype.h> 1562306a36Sopenharmony_ci#include "utils.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistruct st_key_init { 1862306a36Sopenharmony_ci char *name; 1962306a36Sopenharmony_ci int value, shift; 2062306a36Sopenharmony_ci}; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic unsigned char key_data[MAXKEYVAL][16], *kp; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "mapdata.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic const char delims[] = "\t\n "; 2762306a36Sopenharmony_cistatic char *cp; 2862306a36Sopenharmony_cistatic int map_ver = 119; /* an arbitrary number so speakup can check */ 2962306a36Sopenharmony_cistatic int shift_table[17]; 3062306a36Sopenharmony_cistatic int max_states = 1, flags; 3162306a36Sopenharmony_ci/* flags reserved for later, maybe for individual console maps */ 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic int get_shift_value(int state) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci int i; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci for (i = 0; shift_table[i] != state; i++) { 3862306a36Sopenharmony_ci if (shift_table[i] == -1) { 3962306a36Sopenharmony_ci if (i >= 16) 4062306a36Sopenharmony_ci oops("too many shift states", NULL); 4162306a36Sopenharmony_ci shift_table[i] = state; 4262306a36Sopenharmony_ci max_states = i+1; 4362306a36Sopenharmony_ci break; 4462306a36Sopenharmony_ci } 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci return i; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ciint 5062306a36Sopenharmony_cimain(int argc, char *argv[]) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci int value, shift_state, i, spk_val = 0, lock_val = 0; 5362306a36Sopenharmony_ci int max_key_used = 0, num_keys_used = 0; 5462306a36Sopenharmony_ci struct st_key *this; 5562306a36Sopenharmony_ci struct st_key_init *p_init; 5662306a36Sopenharmony_ci char buffer[256]; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci bzero(key_table, sizeof(key_table)); 5962306a36Sopenharmony_ci bzero(key_data, sizeof(key_data)); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci shift_table[0] = 0; 6262306a36Sopenharmony_ci for (i = 1; i <= 16; i++) 6362306a36Sopenharmony_ci shift_table[i] = -1; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (argc < 2) { 6662306a36Sopenharmony_ci fputs("usage: genmap filename\n", stderr); 6762306a36Sopenharmony_ci exit(1); 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci for (p_init = init_key_data; p_init->name[0] != '.'; p_init++) 7162306a36Sopenharmony_ci add_key(p_init->name, p_init->value, p_init->shift); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci open_input(NULL, argv[1]); 7462306a36Sopenharmony_ci while (fgets(buffer, sizeof(buffer), infile)) { 7562306a36Sopenharmony_ci lc++; 7662306a36Sopenharmony_ci value = shift_state = 0; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci cp = strtok(buffer, delims); 7962306a36Sopenharmony_ci if (*cp == '#') 8062306a36Sopenharmony_ci continue; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci while (cp) { 8362306a36Sopenharmony_ci if (*cp == '=') 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci this = find_key(cp); 8662306a36Sopenharmony_ci if (this == NULL) 8762306a36Sopenharmony_ci oops("unknown key/modifier", cp); 8862306a36Sopenharmony_ci if (this->shift == is_shift) { 8962306a36Sopenharmony_ci if (value) 9062306a36Sopenharmony_ci oops("modifiers must come first", cp); 9162306a36Sopenharmony_ci shift_state += this->value; 9262306a36Sopenharmony_ci } else if (this->shift == is_input) 9362306a36Sopenharmony_ci value = this->value; 9462306a36Sopenharmony_ci else 9562306a36Sopenharmony_ci oops("bad modifier or key", cp); 9662306a36Sopenharmony_ci cp = strtok(0, delims); 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci if (!cp) 9962306a36Sopenharmony_ci oops("no = found", NULL); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci cp = strtok(0, delims); 10262306a36Sopenharmony_ci if (!cp) 10362306a36Sopenharmony_ci oops("no speakup function after =", NULL); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci this = find_key(cp); 10662306a36Sopenharmony_ci if (this == NULL || this->shift != is_spk) 10762306a36Sopenharmony_ci oops("invalid speakup function", cp); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci i = get_shift_value(shift_state); 11062306a36Sopenharmony_ci if (key_data[value][i]) { 11162306a36Sopenharmony_ci while (--cp > buffer) 11262306a36Sopenharmony_ci if (!*cp) 11362306a36Sopenharmony_ci *cp = ' '; 11462306a36Sopenharmony_ci oops("two functions on same key combination", cp); 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci key_data[value][i] = (char)this->value; 11762306a36Sopenharmony_ci if (value > max_key_used) 11862306a36Sopenharmony_ci max_key_used = value; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci fclose(infile); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci this = find_key("spk_key"); 12362306a36Sopenharmony_ci if (this) 12462306a36Sopenharmony_ci spk_val = this->value; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci this = find_key("spk_lock"); 12762306a36Sopenharmony_ci if (this) 12862306a36Sopenharmony_ci lock_val = this->value; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci for (lc = 1; lc <= max_key_used; lc++) { 13162306a36Sopenharmony_ci kp = key_data[lc]; 13262306a36Sopenharmony_ci if (!memcmp(key_data[0], kp, 16)) 13362306a36Sopenharmony_ci continue; 13462306a36Sopenharmony_ci num_keys_used++; 13562306a36Sopenharmony_ci for (i = 0; i < max_states; i++) { 13662306a36Sopenharmony_ci if (kp[i] != spk_val && kp[i] != lock_val) 13762306a36Sopenharmony_ci continue; 13862306a36Sopenharmony_ci shift_state = shift_table[i]; 13962306a36Sopenharmony_ci if (shift_state&16) 14062306a36Sopenharmony_ci continue; 14162306a36Sopenharmony_ci shift_state = get_shift_value(shift_state+16); 14262306a36Sopenharmony_ci kp[shift_state] = kp[i]; 14362306a36Sopenharmony_ci /* fill in so we can process the key up, as spk bit will be set */ 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci printf("\t%d, %d, %d,\n\t", map_ver, num_keys_used, max_states); 14862306a36Sopenharmony_ci for (i = 0; i < max_states; i++) 14962306a36Sopenharmony_ci printf("%d, ", shift_table[i]); 15062306a36Sopenharmony_ci printf("%d,", flags); 15162306a36Sopenharmony_ci for (lc = 1; lc <= max_key_used; lc++) { 15262306a36Sopenharmony_ci kp = key_data[lc]; 15362306a36Sopenharmony_ci if (!memcmp(key_data[0], kp, 16)) 15462306a36Sopenharmony_ci continue; 15562306a36Sopenharmony_ci printf("\n\t%d,", lc); 15662306a36Sopenharmony_ci for (i = 0; i < max_states; i++) 15762306a36Sopenharmony_ci printf(" %d,", (unsigned int)kp[i]); 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci printf("\n\t0, %d\n", map_ver); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci exit(0); 16262306a36Sopenharmony_ci} 163