* src/roff/troff/env.cpp (hyphen_trie::read_patterns_file): Fix loop
[s-roff.git] / src / roff / troff / symbol.cpp
blob09f4c98c0e1bfe2cd2b59ddb4b8a4c14b685ee7d
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2002 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 2, or (at your option) any later
10 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
15 for more details.
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "troff.h"
23 #include "symbol.h"
25 const char **symbol::table = 0;
26 int symbol::table_used = 0;
27 int symbol::table_size = 0;
28 char *symbol::block = 0;
29 int symbol::block_size = 0;
31 const symbol NULL_SYMBOL;
32 const symbol EMPTY_SYMBOL("");
34 #ifdef BLOCK_SIZE
35 #undef BLOCK_SIZE
36 #endif
38 const int BLOCK_SIZE = 1024;
39 // the table will increase in size as necessary
40 // the size will be chosen from the following array
41 // add some more if you want
42 static const unsigned int table_sizes[] = {
43 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021,
44 160001, 500009, 1000003, 1500007, 2000003, 0
46 const double FULL_MAX = 0.3; // don't let the table get more than this full
48 static unsigned int hash_string(const char *p)
50 // compute a hash code; this assumes 32-bit unsigned ints
51 // see p436 of Compilers by Aho, Sethi & Ullman
52 // give special treatment to two-character names
53 unsigned int hc = 0, g;
54 if (*p != 0) {
55 hc = *p++;
56 if (*p != 0) {
57 hc <<= 7;
58 hc += *p++;
59 for (; *p != 0; p++) {
60 hc <<= 4;
61 hc += *p;
62 if ((g = (hc & 0xf0000000)) == 0) {
63 hc ^= g >> 24;
64 hc ^= g;
69 return hc;
72 // Tell compiler that a variable is intentionally unused.
73 inline void unused(void *) { }
75 symbol::symbol(const char *p, int how)
77 if (p == 0) {
78 s = 0;
79 return;
81 if (*p == 0) {
82 s = "";
83 return;
85 if (table == 0) {
86 table_size = table_sizes[0];
87 table = (const char **)new char*[table_size];
88 for (int i = 0; i < table_size; i++)
89 table[i] = 0;
90 table_used = 0;
92 unsigned int hc = hash_string(p);
93 const char **pp;
94 for (pp = table + hc % table_size;
95 *pp != 0;
96 (pp == table ? pp = table + table_size - 1 : --pp))
97 if (strcmp(p, *pp) == 0) {
98 s = *pp;
99 return;
101 if (how == MUST_ALREADY_EXIST) {
102 s = 0;
103 return;
105 if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) {
106 const char **old_table = table;
107 unsigned int old_table_size = table_size;
108 int i;
109 for (i = 1; table_sizes[i] <= old_table_size; i++)
110 if (table_sizes[i] == 0)
111 fatal("too many symbols");
112 table_size = table_sizes[i];
113 table_used = 0;
114 table = (const char **)new char*[table_size];
115 for (i = 0; i < table_size; i++)
116 table[i] = 0;
117 for (pp = old_table + old_table_size - 1;
118 pp >= old_table;
119 --pp) {
120 symbol temp(*pp, 1); /* insert it into the new table */
121 unused(&temp);
123 a_delete old_table;
124 for (pp = table + hc % table_size;
125 *pp != 0;
126 (pp == table ? pp = table + table_size - 1 : --pp))
129 ++table_used;
130 if (how == DONT_STORE) {
131 s = *pp = p;
133 else {
134 int len = strlen(p)+1;
135 if (block == 0 || block_size < len) {
136 block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE;
137 block = new char [block_size];
139 (void)strcpy(block, p);
140 s = *pp = block;
141 block += len;
142 block_size -= len;
146 symbol concat(symbol s1, symbol s2)
148 char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1];
149 strcpy(buf, s1.contents());
150 strcat(buf, s2.contents());
151 symbol res(buf);
152 a_delete buf;
153 return res;