1/* Keep a unique copy of strings.
2
3 Copyright (C) 2002-2005, 2009-2015, 2018-2019 Free Software
4 Foundation, Inc.
5
6 This file is part of Bison, the GNU Compiler Compiler.
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21#include <config.h>
22#include "system.h"
23
24#include <error.h>
25#include <hash.h>
26#include <quotearg.h>
27#include <stdarg.h>
28
29#include "uniqstr.h"
30
31/*-----------------------.
32| A uniqstr hash table. |
33`-----------------------*/
34
35/* Initial capacity of uniqstr hash table. */
36#define HT_INITIAL_CAPACITY 257
37
38static struct hash_table *uniqstrs_table = NULL;
39
40/*-------------------------------------.
41| Create the uniqstr for S if needed. |
42`-------------------------------------*/
43
44uniqstr
45uniqstr_new (char const *str)
46{
47 uniqstr res = hash_lookup (uniqstrs_table, str);
48 if (!res)
49 {
50 /* First insertion in the hash. */
51 res = xstrdup (str);
52 if (!hash_insert (uniqstrs_table, res))
53 xalloc_die ();
54 }
55 return res;
56}
57
58uniqstr
59uniqstr_concat (int nargs, ...)
60{
61 va_list args;
62
63 va_start (args, nargs);
64 size_t reslen = 0;
65 for (int i = 0; i < nargs; i++)
66 reslen += strlen (va_arg (args, char const *));
67 va_end (args);
68
69 char *str = xmalloc (reslen + 1);
70 char *p = str;
71
72 va_start (args, nargs);
73 for (int i = 0; i < nargs; i++)
74 {
75 char const *arg = va_arg (args, char const *);
76 size_t arglen = strlen (arg);
77 memcpy (p, arg, arglen);
78 p += arglen;
79 }
80 va_end (args);
81
82 *p = '\0';
83 uniqstr res = hash_insert (uniqstrs_table, str);
84 if (!res)
85 xalloc_die ();
86 if (res != str)
87 free (str);
88 return res;
89}
90
91/*------------------------------.
92| Abort if S is not a uniqstr. |
93`------------------------------*/
94
95void
96uniqstr_assert (char const *str)
97{
98 uniqstr s = hash_lookup (uniqstrs_table, str);
99 if (!s || s != str)
100 {
101 error (0, 0,
102 "not a uniqstr: %s", quotearg (str));
103 abort ();
104 }
105}
106
107
108/*--------------------.
109| Print the uniqstr. |
110`--------------------*/
111
112static inline bool
113uniqstr_print (uniqstr ustr)
114{
115 fprintf (stderr, "%s\n", ustr);
116 return true;
117}
118
119static bool
120uniqstr_print_processor (void *ustr, void *null ATTRIBUTE_UNUSED)
121{
122 return uniqstr_print (ustr);
123}
124
125
126int
127uniqstr_cmp (uniqstr l, uniqstr r)
128{
129 return (l == r ? 0
130 : !l ? -1
131 : !r ? +1
132 : strcmp (l, r));
133}
134
135
136/*-----------------------.
137| A uniqstr hash table. |
138`-----------------------*/
139
140static bool
141hash_compare_uniqstr (void const *m1, void const *m2)
142{
143 return STREQ (m1, m2);
144}
145
146static size_t
147hash_uniqstr (void const *m, size_t tablesize)
148{
149 return hash_string (m, tablesize);
150}
151
152
153/*----------------------------.
154| Create the uniqstrs table. |
155`----------------------------*/
156
157void
158uniqstrs_new (void)
159{
160 uniqstrs_table = hash_xinitialize (HT_INITIAL_CAPACITY,
161 NULL,
162 hash_uniqstr,
163 hash_compare_uniqstr,
164 free);
165}
166
167
168/*-------------------------------------.
169| Perform a task on all the uniqstrs. |
170`-------------------------------------*/
171
172static void
173uniqstrs_do (Hash_processor processor, void *processor_data)
174{
175 hash_do_for_each (uniqstrs_table, processor, processor_data);
176}
177
178
179/*-----------------.
180| Print them all. |
181`-----------------*/
182
183void
184uniqstrs_print (void)
185{
186 uniqstrs_do (uniqstr_print_processor, NULL);
187}
188
189
190/*--------------------.
191| Free the uniqstrs. |
192`--------------------*/
193
194void
195uniqstrs_free (void)
196{
197 hash_free (uniqstrs_table);
198}
199