1 /**************************************************************************** 2 * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29 /**************************************************************************** 30 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 31 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32 * and: Thomas E. Dickey 1996-on * 33 ****************************************************************************/ 34 35 /* 36 * make_hash.c --- build-time program for constructing comp_captab.c 37 * 38 */ 39 40 #include <build.priv.h> 41 42 #include <tic.h> 43 #include <hashsize.h> 44 45 #include <ctype.h> 46 47 MODULE_ID("$Id: make_hash.c,v 1.3 2010/05/22 18:02:50 tom Exp $") 48 49 /* 50 * _nc_make_hash_table() 51 * 52 * Takes the entries in table[] and hashes them into hash_table[] 53 * by name. There are CAPTABSIZE entries in table[] and HASHTABSIZE 54 * slots in hash_table[]. 55 * 56 */ 57 58 #undef MODULE_ID 59 #define MODULE_ID(id) /*nothing */ 60 #include <tinfo/doalloc.c> 61 62 /* 63 * int hash_function(string) 64 * 65 * Computes the hashing function on the given string. 66 * 67 * The current hash function is the sum of each consectutive pair 68 * of characters, taken as two-byte integers, mod HASHTABSIZE. 69 * 70 */ 71 72 static int 73 hash_function(const char *string) 74 { 75 long sum = 0; 76 77 while (*string) { 78 sum += (long) (*string + (*(string + 1) << 8)); 79 string++; 80 } 81 82 return (int) (sum % HASHTABSIZE); 83 } 84 85 static void 86 _nc_make_hash_table(struct name_table_entry *table, 87 HashValue * hash_table) 88 { 89 short i; 90 int hashvalue; 91 int collisions = 0; 92 93 for (i = 0; i < HASHTABSIZE; i++) { 94 hash_table[i] = -1; 95 } 96 for (i = 0; i < CAPTABSIZE; i++) { 97 hashvalue = hash_function(table[i].nte_name); 98 99 if (hash_table[hashvalue] >= 0) 100 collisions++; 101 102 if (hash_table[hashvalue] != 0) 103 table[i].nte_link = hash_table[hashvalue]; 104 hash_table[hashvalue] = i; 105 } 106 107 printf("/* %d collisions out of %d entries */\n", collisions, CAPTABSIZE); 108 } 109 110 /* 111 * This filter reads from standard input a list of tab-delimited columns, 112 * (e.g., from Caps.filtered) computes the hash-value of a specified column and 113 * writes the hashed tables to standard output. 114 * 115 * By compiling the hash table at build time, we're able to make the entire 116 * set of terminfo and termcap tables readonly (and also provide some runtime 117 * performance enhancement). 118 */ 119 120 #define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */ 121 122 static char ** 123 parse_columns(char *buffer) 124 { 125 static char **list; 126 127 int col = 0; 128 129 if (list == 0 && (list = typeCalloc(char *, MAX_COLUMNS)) == 0) 130 return (0); 131 132 if (*buffer != '#') { 133 while (*buffer != '\0') { 134 char *s; 135 for (s = buffer; (*s != '\0') && !isspace(UChar(*s)); s++) 136 /*EMPTY */ ; 137 if (s != buffer) { 138 char mark = *s; 139 *s = '\0'; 140 if ((s - buffer) > 1 141 && (*buffer == '"') 142 && (s[-1] == '"')) { /* strip the quotes */ 143 assert(s > buffer + 1); 144 s[-1] = '\0'; 145 buffer++; 146 } 147 list[col] = buffer; 148 col++; 149 if (mark == '\0') 150 break; 151 while (*++s && isspace(UChar(*s))) 152 /*EMPTY */ ; 153 buffer = s; 154 } else 155 break; 156 } 157 } 158 return col ? list : 0; 159 } 160 161 int 162 main(int argc, char **argv) 163 { 164 struct name_table_entry *name_table = typeCalloc(struct 165 name_table_entry, CAPTABSIZE); 166 HashValue *hash_table = typeCalloc(HashValue, HASHTABSIZE); 167 const char *root_name = ""; 168 int column = 0; 169 int bigstring = 0; 170 int n; 171 char buffer[BUFSIZ]; 172 173 static const char *typenames[] = 174 {"BOOLEAN", "NUMBER", "STRING"}; 175 176 short BoolCount = 0; 177 short NumCount = 0; 178 short StrCount = 0; 179 180 /* The first argument is the column-number (starting with 0). 181 * The second is the root name of the tables to generate. 182 */ 183 if (argc <= 3 184 || (column = atoi(argv[1])) <= 0 185 || (column >= MAX_COLUMNS) 186 || *(root_name = argv[2]) == 0 187 || (bigstring = atoi(argv[3])) < 0 188 || name_table == 0 189 || hash_table == 0) { 190 fprintf(stderr, "usage: make_hash column root_name bigstring\n"); 191 exit(EXIT_FAILURE); 192 } 193 194 /* 195 * Read the table into our arrays. 196 */ 197 for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin);) { 198 char **list, *nlp = strchr(buffer, '\n'); 199 if (nlp) 200 *nlp = '\0'; 201 list = parse_columns(buffer); 202 if (list == 0) /* blank or comment */ 203 continue; 204 name_table[n].nte_link = -1; /* end-of-hash */ 205 name_table[n].nte_name = strdup(list[column]); 206 if (!strcmp(list[2], "bool")) { 207 name_table[n].nte_type = BOOLEAN; 208 name_table[n].nte_index = BoolCount++; 209 } else if (!strcmp(list[2], "num")) { 210 name_table[n].nte_type = NUMBER; 211 name_table[n].nte_index = NumCount++; 212 } else if (!strcmp(list[2], "str")) { 213 name_table[n].nte_type = STRING; 214 name_table[n].nte_index = StrCount++; 215 } else { 216 fprintf(stderr, "Unknown type: %s\n", list[2]); 217 exit(EXIT_FAILURE); 218 } 219 n++; 220 } 221 _nc_make_hash_table(name_table, hash_table); 222 223 /* 224 * Write the compiled tables to standard output 225 */ 226 if (bigstring) { 227 int len = 0; 228 int nxt; 229 230 printf("static const char %s_names_text[] = \\\n", root_name); 231 for (n = 0; n < CAPTABSIZE; n++) { 232 nxt = (int) strlen(name_table[n].nte_name) + 5; 233 if (nxt + len > 72) { 234 printf("\\\n"); 235 len = 0; 236 } 237 printf("\"%s\\0\" ", name_table[n].nte_name); 238 len += nxt; 239 } 240 printf(";\n\n"); 241 242 len = 0; 243 printf("static name_table_data const %s_names_data[] =\n", 244 root_name); 245 printf("{\n"); 246 for (n = 0; n < CAPTABSIZE; n++) { 247 printf("\t{ %15d,\t%10s,\t%3d, %3d }%c\n", 248 len, 249 typenames[name_table[n].nte_type], 250 name_table[n].nte_index, 251 name_table[n].nte_link, 252 n < CAPTABSIZE - 1 ? ',' : ' '); 253 len += (int) strlen(name_table[n].nte_name) + 1; 254 } 255 printf("};\n\n"); 256 printf("static struct name_table_entry *_nc_%s_table = 0;\n\n", root_name); 257 } else { 258 259 printf("static struct name_table_entry %s _nc_%s_table[] =\n", 260 bigstring ? "" : "const", 261 root_name); 262 printf("{\n"); 263 for (n = 0; n < CAPTABSIZE; n++) { 264 sprintf(buffer, "\"%s\"", 265 name_table[n].nte_name); 266 printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n", 267 buffer, 268 typenames[name_table[n].nte_type], 269 name_table[n].nte_index, 270 name_table[n].nte_link, 271 n < CAPTABSIZE - 1 ? ',' : ' '); 272 } 273 printf("};\n\n"); 274 } 275 276 printf("static const HashValue _nc_%s_hash_table[%d] =\n", 277 root_name, 278 HASHTABSIZE + 1); 279 printf("{\n"); 280 for (n = 0; n < HASHTABSIZE; n++) { 281 printf("\t%3d,\n", hash_table[n]); 282 } 283 printf("\t0\t/* base-of-table */\n"); 284 printf("};\n\n"); 285 286 printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", 287 BoolCount, NumCount, StrCount); 288 printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); 289 printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); 290 printf("#endif\n\n"); 291 292 free(hash_table); 293 return EXIT_SUCCESS; 294 } 295