2 /* Copyright (C) 1989-2014 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 const char **symbol::table = 0;
27 int symbol::table_used = 0;
28 int symbol::table_size = 0;
29 char *symbol::block = 0;
30 int symbol::block_size = 0;
32 const symbol NULL_SYMBOL;
33 const symbol EMPTY_SYMBOL("");
39 const int BLOCK_SIZE = 1024;
40 // the table will increase in size as necessary
41 // the size will be chosen from the following array
42 // add some more if you want
43 static const unsigned int table_sizes[] = {
44 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021,
45 160001, 500009, 1000003, 1500007, 2000003, 0
47 const double FULL_MAX = 0.3; // don't let the table get more than this full
49 static unsigned int hash_string(const char *p)
51 // compute a hash code; this assumes 32-bit unsigned ints
52 // see p436 of Compilers by Aho, Sethi & Ullman
53 // give special treatment to two-character names
54 unsigned int hc = 0, g;
60 for (; *p != 0; p++) {
63 if ((g = (hc & 0xf0000000)) == 0) {
73 // Tell compiler that a variable is intentionally unused.
74 inline void unused(void *) { }
76 symbol::symbol(const char *p, int how)
87 table_size = table_sizes[0];
88 table = (const char **)new char*[table_size];
89 for (int i = 0; i < table_size; i++)
93 unsigned int hc = hash_string(p);
95 for (pp = table + hc % table_size;
97 (pp == table ? pp = table + table_size - 1 : --pp))
98 if (strcmp(p, *pp) == 0) {
102 if (how == MUST_ALREADY_EXIST) {
106 if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) {
107 const char **old_table = table;
108 unsigned int old_table_size = table_size;
110 for (i = 1; table_sizes[i] <= old_table_size; i++)
111 if (table_sizes[i] == 0)
112 fatal("too many symbols");
113 table_size = table_sizes[i];
115 table = (const char **)new char*[table_size];
116 for (i = 0; i < table_size; i++)
118 for (pp = old_table + old_table_size - 1;
121 symbol temp(*pp, 1); /* insert it into the new table */
125 for (pp = table + hc % table_size;
127 (pp == table ? pp = table + table_size - 1 : --pp))
131 if (how == DONT_STORE) {
135 int len = strlen(p)+1;
136 if (block == 0 || block_size < len) {
137 block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE;
138 block = new char [block_size];
140 (void)strcpy(block, p);
147 symbol concat(symbol s1, symbol s2)
149 char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1];
150 strcpy(buf, s1.contents());
151 strcat(buf, s2.contents());
157 symbol default_symbol("default");