xref: /netbsd-src/external/gpl2/groff/dist/src/libs/libgroff/symbol.cpp (revision 89a07cf815a29524268025a1139fac4c5190f765)
1 /*	$NetBSD: symbol.cpp,v 1.1.1.1 2016/01/13 18:41:48 christos Exp $	*/
2 
3 // -*- C++ -*-
4 /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004
5    Free Software Foundation, Inc.
6      Written by James Clark (jjc@jclark.com)
7 
8 This file is part of groff.
9 
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.
14 
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.
19 
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. */
23 
24 #include "lib.h"
25 
26 #include "errarg.h"
27 #include "error.h"
28 #include "symbol.h"
29 
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;
35 
36 const symbol NULL_SYMBOL;
37 const symbol EMPTY_SYMBOL("");
38 
39 #ifdef BLOCK_SIZE
40 #undef BLOCK_SIZE
41 #endif
42 
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
50 };
51 const double FULL_MAX = 0.3;	// don't let the table get more than this full
52 
hash_string(const char * p)53 static unsigned int hash_string(const char *p)
54 {
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;
70 	}
71       }
72     }
73   }
74   return hc;
75 }
76 
77 // Tell compiler that a variable is intentionally unused.
unused(void *)78 inline void unused(void *) { }
79 
symbol(const char * p,int how)80 symbol::symbol(const char *p, int how)
81 {
82   if (p == 0) {
83     s = 0;
84     return;
85   }
86   if (*p == 0) {
87     s = "";
88     return;
89   }
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;
96   }
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;
105     }
106   if (how == MUST_ALREADY_EXIST) {
107     s = 0;
108     return;
109   }
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);
127 	 }
128     a_delete old_table;
129     for (pp = table + hc % table_size;
130 	 *pp != 0;
131 	 (pp == table ? pp = table + table_size - 1 : --pp))
132       ;
133   }
134   ++table_used;
135   if (how == DONT_STORE) {
136     s = *pp = p;
137   }
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];
143     }
144     (void)strcpy(block, p);
145     s = *pp = block;
146     block += len;
147     block_size -= len;
148   }
149 }
150 
concat(symbol s1,symbol s2)151 symbol concat(symbol s1, symbol s2)
152 {
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;
159 }
160 
161 symbol default_symbol("default");
162