Sync-to-go: update copyright for 2015
[s-roff.git] / src / lib-roff / symbol.cpp
blobf4f929bb25b728706e507ac9572557bac795a660
1 /*@
2 * Copyright (c) 2014 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
4 * Copyright (C) 1989 - 1992, 2002, 2004
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
8 * This is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2, or (at your option) any later
11 * version.
13 * This is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "config.h"
24 #include "lib.h"
26 #include "errarg.h"
27 #include "error.h"
28 #include "symbol.h"
30 const char **symbol::table = 0;
31 int symbol::table_used = 0;
32 int symbol::table_size = 0;
33 char *symbol::block = 0;
34 int symbol::block_size = 0;
36 const symbol NULL_SYMBOL;
37 const symbol EMPTY_SYMBOL("");
39 #ifdef BLOCK_SIZE
40 # undef BLOCK_SIZE
41 #endif
42 const int BLOCK_SIZE = 1024;
43 // the table will increase in size as necessary
44 // the size will be chosen from the following array
45 // add some more if you want
46 static const unsigned int table_sizes[] = {
47 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021,
48 160001, 500009, 1000003, 1500007, 2000003, 0
50 const double FULL_MAX = 0.3; // don't let the table get more than this full
52 symbol default_symbol("default");
54 static unsigned int hash_string(const char *p) /* FIXME Torek's hash */
56 // compute a hash code; this assumes 32-bit unsigned ints
57 // see p436 of Compilers by Aho, Sethi & Ullman
58 // give special treatment to two-character names
59 unsigned int hc = 0, g;
60 if (*p != 0) {
61 hc = *p++;
62 if (*p != 0) {
63 hc <<= 7;
64 hc += *p++;
65 for (; *p != 0; p++) {
66 hc <<= 4;
67 hc += *p;
68 if ((g = (hc & 0xf0000000)) == 0) {
69 hc ^= g >> 24;
70 hc ^= g;
75 return hc;
78 // Tell compiler that a variable is intentionally unused.
79 inline void unused(void *) { }
81 symbol::symbol(const char *p, int how)
83 if (p == 0) {
84 s = 0;
85 return;
87 if (*p == 0) {
88 s = "";
89 return;
91 if (table == 0) {
92 table_size = table_sizes[0];
93 table = (const char **)new char*[table_size];
94 for (int i = 0; i < table_size; i++)
95 table[i] = 0;
96 table_used = 0;
98 unsigned int hc = hash_string(p);
99 const char **pp;
100 for (pp = table + hc % table_size;
101 *pp != 0;
102 (pp == table ? pp = table + table_size - 1 : --pp))
103 if (strcmp(p, *pp) == 0) {
104 s = *pp;
105 return;
107 if (how == MUST_ALREADY_EXIST) {
108 s = 0;
109 return;
111 if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) {
112 const char **old_table = table;
113 unsigned int old_table_size = table_size;
114 int i;
115 for (i = 1; table_sizes[i] <= old_table_size; i++)
116 if (table_sizes[i] == 0)
117 fatal("too many symbols");
118 table_size = table_sizes[i];
119 table_used = 0;
120 table = (const char **)new char*[table_size];
121 for (i = 0; i < table_size; i++)
122 table[i] = 0;
123 for (pp = old_table + old_table_size - 1;
124 pp >= old_table;
125 --pp) {
126 symbol temp(*pp, 1); /* insert it into the new table */
127 unused(&temp);
129 a_delete old_table;
130 for (pp = table + hc % table_size;
131 *pp != 0;
132 (pp == table ? pp = table + table_size - 1 : --pp))
135 ++table_used;
136 if (how == DONT_STORE) {
137 s = *pp = p;
139 else {
140 int len = strlen(p)+1;
141 if (block == 0 || block_size < len) {
142 block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE;
143 block = new char [block_size];
145 (void)strcpy(block, p);
146 s = *pp = block;
147 block += len;
148 block_size -= len;
152 symbol concat(symbol s1, symbol s2)
154 char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1];
155 strcpy(buf, s1.contents());
156 strcat(buf, s2.contents());
157 symbol res(buf);
158 a_delete buf;
159 return res;
162 // s-it2-mode