xref: /freebsd/contrib/ncurses/ncurses/tinfo/make_hash.c (revision 73f0a83d68863a383fd8953972cd36eb6420ec7d)
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