106bfebdeSXin LI /**************************************************************************** 2*73f0a83dSXin LI * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. * 306bfebdeSXin LI * * 406bfebdeSXin LI * Permission is hereby granted, free of charge, to any person obtaining a * 506bfebdeSXin LI * copy of this software and associated documentation files (the * 606bfebdeSXin LI * "Software"), to deal in the Software without restriction, including * 706bfebdeSXin LI * without limitation the rights to use, copy, modify, merge, publish, * 806bfebdeSXin LI * distribute, distribute with modifications, sublicense, and/or sell * 906bfebdeSXin LI * copies of the Software, and to permit persons to whom the Software is * 1006bfebdeSXin LI * furnished to do so, subject to the following conditions: * 1106bfebdeSXin LI * * 1206bfebdeSXin LI * The above copyright notice and this permission notice shall be included * 1306bfebdeSXin LI * in all copies or substantial portions of the Software. * 1406bfebdeSXin LI * * 1506bfebdeSXin LI * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1606bfebdeSXin LI * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1706bfebdeSXin LI * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1806bfebdeSXin LI * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1906bfebdeSXin LI * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2006bfebdeSXin LI * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2106bfebdeSXin LI * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2206bfebdeSXin LI * * 2306bfebdeSXin LI * Except as contained in this notice, the name(s) of the above copyright * 2406bfebdeSXin LI * holders shall not be used in advertising or otherwise to promote the * 2506bfebdeSXin LI * sale, use or other dealings in this Software without prior written * 2606bfebdeSXin LI * authorization. * 2706bfebdeSXin LI ****************************************************************************/ 2806bfebdeSXin LI 2906bfebdeSXin LI /**************************************************************************** 3006bfebdeSXin LI * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3106bfebdeSXin LI * and: Eric S. Raymond <esr@snark.thyrsus.com> * 3206bfebdeSXin LI * and: Thomas E. Dickey 1996-on * 3306bfebdeSXin LI ****************************************************************************/ 3406bfebdeSXin LI 3506bfebdeSXin LI /* 3606bfebdeSXin LI * make_hash.c --- build-time program for constructing comp_captab.c 3706bfebdeSXin LI * 3806bfebdeSXin LI */ 3906bfebdeSXin LI 4006bfebdeSXin LI #include <build.priv.h> 4106bfebdeSXin LI 4206bfebdeSXin LI #include <tic.h> 4306bfebdeSXin LI #include <hashsize.h> 4406bfebdeSXin LI 4506bfebdeSXin LI #include <ctype.h> 4606bfebdeSXin LI 47*73f0a83dSXin LI MODULE_ID("$Id: make_hash.c,v 1.13 2013/09/28 20:55:47 tom Exp $") 4806bfebdeSXin LI 4906bfebdeSXin LI /* 5006bfebdeSXin LI * _nc_make_hash_table() 5106bfebdeSXin LI * 5206bfebdeSXin LI * Takes the entries in table[] and hashes them into hash_table[] 5306bfebdeSXin LI * by name. There are CAPTABSIZE entries in table[] and HASHTABSIZE 5406bfebdeSXin LI * slots in hash_table[]. 5506bfebdeSXin LI * 5606bfebdeSXin LI */ 5706bfebdeSXin LI 5806bfebdeSXin LI #undef MODULE_ID 5906bfebdeSXin LI #define MODULE_ID(id) /*nothing */ 6006bfebdeSXin LI #include <tinfo/doalloc.c> 6106bfebdeSXin LI 62*73f0a83dSXin LI static void 63*73f0a83dSXin LI failed(const char *s) 64*73f0a83dSXin LI { 65*73f0a83dSXin LI perror(s); 66*73f0a83dSXin LI exit(EXIT_FAILURE); 67*73f0a83dSXin LI } 68*73f0a83dSXin LI 69*73f0a83dSXin LI static char * 70*73f0a83dSXin LI strmalloc(char *s) 71*73f0a83dSXin LI { 72*73f0a83dSXin LI size_t need = strlen(s) + 1; 73*73f0a83dSXin LI char *result = malloc(need); 74*73f0a83dSXin LI if (result == 0) 75*73f0a83dSXin LI failed("strmalloc"); 76*73f0a83dSXin LI _nc_STRCPY(result, s, need); 77*73f0a83dSXin LI return result; 78*73f0a83dSXin LI } 79*73f0a83dSXin LI 8006bfebdeSXin LI /* 8106bfebdeSXin LI * int hash_function(string) 8206bfebdeSXin LI * 8306bfebdeSXin LI * Computes the hashing function on the given string. 8406bfebdeSXin LI * 8506bfebdeSXin LI * The current hash function is the sum of each consectutive pair 8606bfebdeSXin LI * of characters, taken as two-byte integers, mod HASHTABSIZE. 8706bfebdeSXin LI * 8806bfebdeSXin LI */ 8906bfebdeSXin LI 9006bfebdeSXin LI static int 9106bfebdeSXin LI hash_function(const char *string) 9206bfebdeSXin LI { 9306bfebdeSXin LI long sum = 0; 9406bfebdeSXin LI 9506bfebdeSXin LI while (*string) { 9606bfebdeSXin LI sum += (long) (*string + (*(string + 1) << 8)); 9706bfebdeSXin LI string++; 9806bfebdeSXin LI } 9906bfebdeSXin LI 10006bfebdeSXin LI return (int) (sum % HASHTABSIZE); 10106bfebdeSXin LI } 10206bfebdeSXin LI 10306bfebdeSXin LI static void 10406bfebdeSXin LI _nc_make_hash_table(struct name_table_entry *table, 10506bfebdeSXin LI HashValue * hash_table) 10606bfebdeSXin LI { 10706bfebdeSXin LI short i; 10806bfebdeSXin LI int hashvalue; 10906bfebdeSXin LI int collisions = 0; 11006bfebdeSXin LI 11106bfebdeSXin LI for (i = 0; i < HASHTABSIZE; i++) { 11206bfebdeSXin LI hash_table[i] = -1; 11306bfebdeSXin LI } 11406bfebdeSXin LI for (i = 0; i < CAPTABSIZE; i++) { 11506bfebdeSXin LI hashvalue = hash_function(table[i].nte_name); 11606bfebdeSXin LI 11706bfebdeSXin LI if (hash_table[hashvalue] >= 0) 11806bfebdeSXin LI collisions++; 11906bfebdeSXin LI 12006bfebdeSXin LI if (hash_table[hashvalue] != 0) 12106bfebdeSXin LI table[i].nte_link = hash_table[hashvalue]; 12206bfebdeSXin LI hash_table[hashvalue] = i; 12306bfebdeSXin LI } 12406bfebdeSXin LI 12506bfebdeSXin LI printf("/* %d collisions out of %d entries */\n", collisions, CAPTABSIZE); 12606bfebdeSXin LI } 12706bfebdeSXin LI 12806bfebdeSXin LI /* 12906bfebdeSXin LI * This filter reads from standard input a list of tab-delimited columns, 13006bfebdeSXin LI * (e.g., from Caps.filtered) computes the hash-value of a specified column and 13106bfebdeSXin LI * writes the hashed tables to standard output. 13206bfebdeSXin LI * 13306bfebdeSXin LI * By compiling the hash table at build time, we're able to make the entire 13406bfebdeSXin LI * set of terminfo and termcap tables readonly (and also provide some runtime 13506bfebdeSXin LI * performance enhancement). 13606bfebdeSXin LI */ 13706bfebdeSXin LI 13806bfebdeSXin LI #define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */ 13906bfebdeSXin LI 140*73f0a83dSXin LI static int 141*73f0a83dSXin LI count_columns(char **list) 142*73f0a83dSXin LI { 143*73f0a83dSXin LI int result = 0; 144*73f0a83dSXin LI if (list != 0) { 145*73f0a83dSXin LI while (*list++) { 146*73f0a83dSXin LI ++result; 147*73f0a83dSXin LI } 148*73f0a83dSXin LI } 149*73f0a83dSXin LI return result; 150*73f0a83dSXin LI } 151*73f0a83dSXin LI 15206bfebdeSXin LI static char ** 15306bfebdeSXin LI parse_columns(char *buffer) 15406bfebdeSXin LI { 15506bfebdeSXin LI static char **list; 15606bfebdeSXin LI 15706bfebdeSXin LI int col = 0; 15806bfebdeSXin LI 159*73f0a83dSXin LI if (list == 0 && (list = typeCalloc(char *, (MAX_COLUMNS + 1))) == 0) 16006bfebdeSXin LI return (0); 16106bfebdeSXin LI 16206bfebdeSXin LI if (*buffer != '#') { 16306bfebdeSXin LI while (*buffer != '\0') { 16406bfebdeSXin LI char *s; 16506bfebdeSXin LI for (s = buffer; (*s != '\0') && !isspace(UChar(*s)); s++) 16606bfebdeSXin LI /*EMPTY */ ; 16706bfebdeSXin LI if (s != buffer) { 16806bfebdeSXin LI char mark = *s; 16906bfebdeSXin LI *s = '\0'; 17006bfebdeSXin LI if ((s - buffer) > 1 17106bfebdeSXin LI && (*buffer == '"') 17206bfebdeSXin LI && (s[-1] == '"')) { /* strip the quotes */ 17306bfebdeSXin LI assert(s > buffer + 1); 17406bfebdeSXin LI s[-1] = '\0'; 17506bfebdeSXin LI buffer++; 17606bfebdeSXin LI } 17706bfebdeSXin LI list[col] = buffer; 17806bfebdeSXin LI col++; 17906bfebdeSXin LI if (mark == '\0') 18006bfebdeSXin LI break; 18106bfebdeSXin LI while (*++s && isspace(UChar(*s))) 18206bfebdeSXin LI /*EMPTY */ ; 18306bfebdeSXin LI buffer = s; 18406bfebdeSXin LI } else 18506bfebdeSXin LI break; 18606bfebdeSXin LI } 18706bfebdeSXin LI } 18806bfebdeSXin LI return col ? list : 0; 18906bfebdeSXin LI } 19006bfebdeSXin LI 19106bfebdeSXin LI int 19206bfebdeSXin LI main(int argc, char **argv) 19306bfebdeSXin LI { 19406bfebdeSXin LI struct name_table_entry *name_table = typeCalloc(struct 19506bfebdeSXin LI name_table_entry, CAPTABSIZE); 19606bfebdeSXin LI HashValue *hash_table = typeCalloc(HashValue, HASHTABSIZE); 19706bfebdeSXin LI const char *root_name = ""; 19806bfebdeSXin LI int column = 0; 19906bfebdeSXin LI int bigstring = 0; 20006bfebdeSXin LI int n; 20106bfebdeSXin LI char buffer[BUFSIZ]; 20206bfebdeSXin LI 20306bfebdeSXin LI static const char *typenames[] = 20406bfebdeSXin LI {"BOOLEAN", "NUMBER", "STRING"}; 20506bfebdeSXin LI 20606bfebdeSXin LI short BoolCount = 0; 20706bfebdeSXin LI short NumCount = 0; 20806bfebdeSXin LI short StrCount = 0; 20906bfebdeSXin LI 21006bfebdeSXin LI /* The first argument is the column-number (starting with 0). 21106bfebdeSXin LI * The second is the root name of the tables to generate. 21206bfebdeSXin LI */ 21306bfebdeSXin LI if (argc <= 3 21406bfebdeSXin LI || (column = atoi(argv[1])) <= 0 21506bfebdeSXin LI || (column >= MAX_COLUMNS) 21606bfebdeSXin LI || *(root_name = argv[2]) == 0 21706bfebdeSXin LI || (bigstring = atoi(argv[3])) < 0 21806bfebdeSXin LI || name_table == 0 21906bfebdeSXin LI || hash_table == 0) { 22006bfebdeSXin LI fprintf(stderr, "usage: make_hash column root_name bigstring\n"); 22106bfebdeSXin LI exit(EXIT_FAILURE); 22206bfebdeSXin LI } 22306bfebdeSXin LI 22406bfebdeSXin LI /* 22506bfebdeSXin LI * Read the table into our arrays. 22606bfebdeSXin LI */ 22706bfebdeSXin LI for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin);) { 22806bfebdeSXin LI char **list, *nlp = strchr(buffer, '\n'); 22906bfebdeSXin LI if (nlp) 23006bfebdeSXin LI *nlp = '\0'; 23106bfebdeSXin LI list = parse_columns(buffer); 23206bfebdeSXin LI if (list == 0) /* blank or comment */ 23306bfebdeSXin LI continue; 234*73f0a83dSXin LI if (column > count_columns(list)) { 235*73f0a83dSXin LI fprintf(stderr, "expected %d columns, have %d:\n%s\n", 236*73f0a83dSXin LI column, 237*73f0a83dSXin LI count_columns(list), 238*73f0a83dSXin LI buffer); 239*73f0a83dSXin LI exit(EXIT_FAILURE); 240*73f0a83dSXin LI } 24106bfebdeSXin LI name_table[n].nte_link = -1; /* end-of-hash */ 242*73f0a83dSXin LI name_table[n].nte_name = strmalloc(list[column]); 24306bfebdeSXin LI if (!strcmp(list[2], "bool")) { 24406bfebdeSXin LI name_table[n].nte_type = BOOLEAN; 24506bfebdeSXin LI name_table[n].nte_index = BoolCount++; 24606bfebdeSXin LI } else if (!strcmp(list[2], "num")) { 24706bfebdeSXin LI name_table[n].nte_type = NUMBER; 24806bfebdeSXin LI name_table[n].nte_index = NumCount++; 24906bfebdeSXin LI } else if (!strcmp(list[2], "str")) { 25006bfebdeSXin LI name_table[n].nte_type = STRING; 25106bfebdeSXin LI name_table[n].nte_index = StrCount++; 25206bfebdeSXin LI } else { 25306bfebdeSXin LI fprintf(stderr, "Unknown type: %s\n", list[2]); 25406bfebdeSXin LI exit(EXIT_FAILURE); 25506bfebdeSXin LI } 25606bfebdeSXin LI n++; 25706bfebdeSXin LI } 25806bfebdeSXin LI _nc_make_hash_table(name_table, hash_table); 25906bfebdeSXin LI 26006bfebdeSXin LI /* 26106bfebdeSXin LI * Write the compiled tables to standard output 26206bfebdeSXin LI */ 26306bfebdeSXin LI if (bigstring) { 26406bfebdeSXin LI int len = 0; 26506bfebdeSXin LI int nxt; 26606bfebdeSXin LI 26706bfebdeSXin LI printf("static const char %s_names_text[] = \\\n", root_name); 26806bfebdeSXin LI for (n = 0; n < CAPTABSIZE; n++) { 26906bfebdeSXin LI nxt = (int) strlen(name_table[n].nte_name) + 5; 27006bfebdeSXin LI if (nxt + len > 72) { 27106bfebdeSXin LI printf("\\\n"); 27206bfebdeSXin LI len = 0; 27306bfebdeSXin LI } 27406bfebdeSXin LI printf("\"%s\\0\" ", name_table[n].nte_name); 27506bfebdeSXin LI len += nxt; 27606bfebdeSXin LI } 27706bfebdeSXin LI printf(";\n\n"); 27806bfebdeSXin LI 27906bfebdeSXin LI len = 0; 28006bfebdeSXin LI printf("static name_table_data const %s_names_data[] =\n", 28106bfebdeSXin LI root_name); 28206bfebdeSXin LI printf("{\n"); 28306bfebdeSXin LI for (n = 0; n < CAPTABSIZE; n++) { 28406bfebdeSXin LI printf("\t{ %15d,\t%10s,\t%3d, %3d }%c\n", 28506bfebdeSXin LI len, 28606bfebdeSXin LI typenames[name_table[n].nte_type], 28706bfebdeSXin LI name_table[n].nte_index, 28806bfebdeSXin LI name_table[n].nte_link, 28906bfebdeSXin LI n < CAPTABSIZE - 1 ? ',' : ' '); 29006bfebdeSXin LI len += (int) strlen(name_table[n].nte_name) + 1; 29106bfebdeSXin LI } 29206bfebdeSXin LI printf("};\n\n"); 29306bfebdeSXin LI printf("static struct name_table_entry *_nc_%s_table = 0;\n\n", root_name); 29406bfebdeSXin LI } else { 29506bfebdeSXin LI 296*73f0a83dSXin LI printf("static struct name_table_entry const _nc_%s_table[] =\n", 29706bfebdeSXin LI root_name); 29806bfebdeSXin LI printf("{\n"); 29906bfebdeSXin LI for (n = 0; n < CAPTABSIZE; n++) { 300*73f0a83dSXin LI _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "\"%s\"", 30106bfebdeSXin LI name_table[n].nte_name); 30206bfebdeSXin LI printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n", 30306bfebdeSXin LI buffer, 30406bfebdeSXin LI typenames[name_table[n].nte_type], 30506bfebdeSXin LI name_table[n].nte_index, 30606bfebdeSXin LI name_table[n].nte_link, 30706bfebdeSXin LI n < CAPTABSIZE - 1 ? ',' : ' '); 30806bfebdeSXin LI } 30906bfebdeSXin LI printf("};\n\n"); 31006bfebdeSXin LI } 31106bfebdeSXin LI 31206bfebdeSXin LI printf("static const HashValue _nc_%s_hash_table[%d] =\n", 31306bfebdeSXin LI root_name, 31406bfebdeSXin LI HASHTABSIZE + 1); 31506bfebdeSXin LI printf("{\n"); 31606bfebdeSXin LI for (n = 0; n < HASHTABSIZE; n++) { 31706bfebdeSXin LI printf("\t%3d,\n", hash_table[n]); 31806bfebdeSXin LI } 31906bfebdeSXin LI printf("\t0\t/* base-of-table */\n"); 32006bfebdeSXin LI printf("};\n\n"); 32106bfebdeSXin LI 32206bfebdeSXin LI printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", 32306bfebdeSXin LI BoolCount, NumCount, StrCount); 32406bfebdeSXin LI printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); 32506bfebdeSXin LI printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); 32606bfebdeSXin LI printf("#endif\n\n"); 32706bfebdeSXin LI 32806bfebdeSXin LI free(hash_table); 32906bfebdeSXin LI return EXIT_SUCCESS; 33006bfebdeSXin LI } 331