1 /**************************************************************************** 2 * Copyright (c) 1998-2012,2013 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.13 2013/09/28 20:55:47 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 static void 63 failed(const char *s) 64 { 65 perror(s); 66 exit(EXIT_FAILURE); 67 } 68 69 static char * 70 strmalloc(char *s) 71 { 72 size_t need = strlen(s) + 1; 73 char *result = malloc(need); 74 if (result == 0) 75 failed("strmalloc"); 76 _nc_STRCPY(result, s, need); 77 return result; 78 } 79 80 /* 81 * int hash_function(string) 82 * 83 * Computes the hashing function on the given string. 84 * 85 * The current hash function is the sum of each consectutive pair 86 * of characters, taken as two-byte integers, mod HASHTABSIZE. 87 * 88 */ 89 90 static int 91 hash_function(const char *string) 92 { 93 long sum = 0; 94 95 while (*string) { 96 sum += (long) (*string + (*(string + 1) << 8)); 97 string++; 98 } 99 100 return (int) (sum % HASHTABSIZE); 101 } 102 103 static void 104 _nc_make_hash_table(struct name_table_entry *table, 105 HashValue * hash_table) 106 { 107 short i; 108 int hashvalue; 109 int collisions = 0; 110 111 for (i = 0; i < HASHTABSIZE; i++) { 112 hash_table[i] = -1; 113 } 114 for (i = 0; i < CAPTABSIZE; i++) { 115 hashvalue = hash_function(table[i].nte_name); 116 117 if (hash_table[hashvalue] >= 0) 118 collisions++; 119 120 if (hash_table[hashvalue] != 0) 121 table[i].nte_link = hash_table[hashvalue]; 122 hash_table[hashvalue] = i; 123 } 124 125 printf("/* %d collisions out of %d entries */\n", collisions, CAPTABSIZE); 126 } 127 128 /* 129 * This filter reads from standard input a list of tab-delimited columns, 130 * (e.g., from Caps.filtered) computes the hash-value of a specified column and 131 * writes the hashed tables to standard output. 132 * 133 * By compiling the hash table at build time, we're able to make the entire 134 * set of terminfo and termcap tables readonly (and also provide some runtime 135 * performance enhancement). 136 */ 137 138 #define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */ 139 140 static int 141 count_columns(char **list) 142 { 143 int result = 0; 144 if (list != 0) { 145 while (*list++) { 146 ++result; 147 } 148 } 149 return result; 150 } 151 152 static char ** 153 parse_columns(char *buffer) 154 { 155 static char **list; 156 157 int col = 0; 158 159 if (list == 0 && (list = typeCalloc(char *, (MAX_COLUMNS + 1))) == 0) 160 return (0); 161 162 if (*buffer != '#') { 163 while (*buffer != '\0') { 164 char *s; 165 for (s = buffer; (*s != '\0') && !isspace(UChar(*s)); s++) 166 /*EMPTY */ ; 167 if (s != buffer) { 168 char mark = *s; 169 *s = '\0'; 170 if ((s - buffer) > 1 171 && (*buffer == '"') 172 && (s[-1] == '"')) { /* strip the quotes */ 173 assert(s > buffer + 1); 174 s[-1] = '\0'; 175 buffer++; 176 } 177 list[col] = buffer; 178 col++; 179 if (mark == '\0') 180 break; 181 while (*++s && isspace(UChar(*s))) 182 /*EMPTY */ ; 183 buffer = s; 184 } else 185 break; 186 } 187 } 188 return col ? list : 0; 189 } 190 191 int 192 main(int argc, char **argv) 193 { 194 struct name_table_entry *name_table = typeCalloc(struct 195 name_table_entry, CAPTABSIZE); 196 HashValue *hash_table = typeCalloc(HashValue, HASHTABSIZE); 197 const char *root_name = ""; 198 int column = 0; 199 int bigstring = 0; 200 int n; 201 char buffer[BUFSIZ]; 202 203 static const char *typenames[] = 204 {"BOOLEAN", "NUMBER", "STRING"}; 205 206 short BoolCount = 0; 207 short NumCount = 0; 208 short StrCount = 0; 209 210 /* The first argument is the column-number (starting with 0). 211 * The second is the root name of the tables to generate. 212 */ 213 if (argc <= 3 214 || (column = atoi(argv[1])) <= 0 215 || (column >= MAX_COLUMNS) 216 || *(root_name = argv[2]) == 0 217 || (bigstring = atoi(argv[3])) < 0 218 || name_table == 0 219 || hash_table == 0) { 220 fprintf(stderr, "usage: make_hash column root_name bigstring\n"); 221 exit(EXIT_FAILURE); 222 } 223 224 /* 225 * Read the table into our arrays. 226 */ 227 for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin);) { 228 char **list, *nlp = strchr(buffer, '\n'); 229 if (nlp) 230 *nlp = '\0'; 231 list = parse_columns(buffer); 232 if (list == 0) /* blank or comment */ 233 continue; 234 if (column > count_columns(list)) { 235 fprintf(stderr, "expected %d columns, have %d:\n%s\n", 236 column, 237 count_columns(list), 238 buffer); 239 exit(EXIT_FAILURE); 240 } 241 name_table[n].nte_link = -1; /* end-of-hash */ 242 name_table[n].nte_name = strmalloc(list[column]); 243 if (!strcmp(list[2], "bool")) { 244 name_table[n].nte_type = BOOLEAN; 245 name_table[n].nte_index = BoolCount++; 246 } else if (!strcmp(list[2], "num")) { 247 name_table[n].nte_type = NUMBER; 248 name_table[n].nte_index = NumCount++; 249 } else if (!strcmp(list[2], "str")) { 250 name_table[n].nte_type = STRING; 251 name_table[n].nte_index = StrCount++; 252 } else { 253 fprintf(stderr, "Unknown type: %s\n", list[2]); 254 exit(EXIT_FAILURE); 255 } 256 n++; 257 } 258 _nc_make_hash_table(name_table, hash_table); 259 260 /* 261 * Write the compiled tables to standard output 262 */ 263 if (bigstring) { 264 int len = 0; 265 int nxt; 266 267 printf("static const char %s_names_text[] = \\\n", root_name); 268 for (n = 0; n < CAPTABSIZE; n++) { 269 nxt = (int) strlen(name_table[n].nte_name) + 5; 270 if (nxt + len > 72) { 271 printf("\\\n"); 272 len = 0; 273 } 274 printf("\"%s\\0\" ", name_table[n].nte_name); 275 len += nxt; 276 } 277 printf(";\n\n"); 278 279 len = 0; 280 printf("static name_table_data const %s_names_data[] =\n", 281 root_name); 282 printf("{\n"); 283 for (n = 0; n < CAPTABSIZE; n++) { 284 printf("\t{ %15d,\t%10s,\t%3d, %3d }%c\n", 285 len, 286 typenames[name_table[n].nte_type], 287 name_table[n].nte_index, 288 name_table[n].nte_link, 289 n < CAPTABSIZE - 1 ? ',' : ' '); 290 len += (int) strlen(name_table[n].nte_name) + 1; 291 } 292 printf("};\n\n"); 293 printf("static struct name_table_entry *_nc_%s_table = 0;\n\n", root_name); 294 } else { 295 296 printf("static struct name_table_entry const _nc_%s_table[] =\n", 297 root_name); 298 printf("{\n"); 299 for (n = 0; n < CAPTABSIZE; n++) { 300 _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "\"%s\"", 301 name_table[n].nte_name); 302 printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n", 303 buffer, 304 typenames[name_table[n].nte_type], 305 name_table[n].nte_index, 306 name_table[n].nte_link, 307 n < CAPTABSIZE - 1 ? ',' : ' '); 308 } 309 printf("};\n\n"); 310 } 311 312 printf("static const HashValue _nc_%s_hash_table[%d] =\n", 313 root_name, 314 HASHTABSIZE + 1); 315 printf("{\n"); 316 for (n = 0; n < HASHTABSIZE; n++) { 317 printf("\t%3d,\n", hash_table[n]); 318 } 319 printf("\t0\t/* base-of-table */\n"); 320 printf("};\n\n"); 321 322 printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", 323 BoolCount, NumCount, StrCount); 324 printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); 325 printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); 326 printf("#endif\n\n"); 327 328 free(hash_table); 329 return EXIT_SUCCESS; 330 } 331