Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / groff / src / libs / libgroff / symbol.cpp
blob0f1b8f988f419a1b8f1b42fe46591b633747fff8
1 /* $NetBSD$ */
3 // -*- C++ -*-
4 /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004
5 Free Software Foundation, Inc.
6 Written by James Clark (jjc@jclark.com)
8 This file is part of groff.
10 groff is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
13 version.
15 groff is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License along
21 with groff; see the file COPYING. If not, write to the Free Software
22 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
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
43 const int BLOCK_SIZE = 1024;
44 // the table will increase in size as necessary
45 // the size will be chosen from the following array
46 // add some more if you want
47 static const unsigned int table_sizes[] = {
48 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021,
49 160001, 500009, 1000003, 1500007, 2000003, 0
51 const double FULL_MAX = 0.3; // don't let the table get more than this full
53 static unsigned int hash_string(const char *p)
55 // compute a hash code; this assumes 32-bit unsigned ints
56 // see p436 of Compilers by Aho, Sethi & Ullman
57 // give special treatment to two-character names
58 unsigned int hc = 0, g;
59 if (*p != 0) {
60 hc = *p++;
61 if (*p != 0) {
62 hc <<= 7;
63 hc += *p++;
64 for (; *p != 0; p++) {
65 hc <<= 4;
66 hc += *p;
67 if ((g = (hc & 0xf0000000)) == 0) {
68 hc ^= g >> 24;
69 hc ^= g;
74 return hc;
77 // Tell compiler that a variable is intentionally unused.
78 inline void unused(void *) { }
80 symbol::symbol(const char *p, int how)
82 if (p == 0) {
83 s = 0;
84 return;
86 if (*p == 0) {
87 s = "";
88 return;
90 if (table == 0) {
91 table_size = table_sizes[0];
92 table = (const char **)new char*[table_size];
93 for (int i = 0; i < table_size; i++)
94 table[i] = 0;
95 table_used = 0;
97 unsigned int hc = hash_string(p);
98 const char **pp;
99 for (pp = table + hc % table_size;
100 *pp != 0;
101 (pp == table ? pp = table + table_size - 1 : --pp))
102 if (strcmp(p, *pp) == 0) {
103 s = *pp;
104 return;
106 if (how == MUST_ALREADY_EXIST) {
107 s = 0;
108 return;
110 if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) {
111 const char **old_table = table;
112 unsigned int old_table_size = table_size;
113 int i;
114 for (i = 1; table_sizes[i] <= old_table_size; i++)
115 if (table_sizes[i] == 0)
116 fatal("too many symbols");
117 table_size = table_sizes[i];
118 table_used = 0;
119 table = (const char **)new char*[table_size];
120 for (i = 0; i < table_size; i++)
121 table[i] = 0;
122 for (pp = old_table + old_table_size - 1;
123 pp >= old_table;
124 --pp) {
125 symbol temp(*pp, 1); /* insert it into the new table */
126 unused(&temp);
128 a_delete old_table;
129 for (pp = table + hc % table_size;
130 *pp != 0;
131 (pp == table ? pp = table + table_size - 1 : --pp))
134 ++table_used;
135 if (how == DONT_STORE) {
136 s = *pp = p;
138 else {
139 int len = strlen(p)+1;
140 if (block == 0 || block_size < len) {
141 block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE;
142 block = new char [block_size];
144 (void)strcpy(block, p);
145 s = *pp = block;
146 block += len;
147 block_size -= len;
151 symbol concat(symbol s1, symbol s2)
153 char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1];
154 strcpy(buf, s1.contents());
155 strcat(buf, s2.contents());
156 symbol res(buf);
157 a_delete buf;
158 return res;
161 symbol default_symbol("default");