a90b0b723eadf9595979b7e9c3fbed2d89380a55
[libfirm] / ir / ident / ident.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /*
21  * Project:     libFIRM
22  * File name:   ir/common/ident.c
23  * Purpose:     Hash table to store names.
24  * Author:      Goetz Lindenmaier
25  * Modified by:
26  * Created:
27  * CVS-ID:      $Id$
28  * Copyright:   (c) 1999-2003 Universität Karlsruhe
29  */
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <assert.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <stddef.h>
39 #include <stdlib.h>
40
41 #ifdef FIRM_ENABLE_WCHAR
42 #include <wchar.h>
43 #endif
44
45 #include "ident_t.h"
46 #include "set.h"
47 #include "xmalloc.h"
48
49 /* for debugging only, not the real implementation */
50 struct _ident {
51   char reserved[sizeof(unsigned) + sizeof(size_t)];
52   char data[1];
53 };
54
55 /** The current ident module implementation. */
56 static ident_if_t impl;
57
58 /**
59  * Stores a string in the ident module and returns a handle for the string.
60  *
61  * @param handle   the handle for the set
62  * @param str      the string which shall be stored
63  * @param len      length of str in bytes
64  *
65  * @return id - a handle for the generated ident
66  *
67  * Default implementation using libfirm sets.
68  */
69 static ident *set_new_id_from_chars(void *handle, const char *str, int len)
70 {
71   set *id_set = handle;
72
73   /* GL: Who added this assert?  And why? */
74   //assert(len > 0);
75   return (ident *)set_hinsert0(id_set, str, len, ID_HASH(unsigned char, str, len));
76 }
77
78 /**
79  * Stores a string in the ident module and returns a handle for the string.
80  *
81  * @param handle   the handle for the set
82  * @param str      the string (or whatever) which shall be stored
83  *
84  * Default implementation using libfirm sets.
85  */
86 static ident *set_new_id_from_str(void *handle, const char *str)
87 {
88   assert(str);
89   return (ident *)set_new_id_from_chars(handle, str, strlen(str));
90 }
91
92 /**
93  * Returns a string represented by an ident.
94  *
95  * @param handle   the handle for the set
96  * @param id       the ident
97  *
98  * Default implementation using libfirm sets.
99  */
100 static const char *set_get_id_str(void *handle, ident *id)
101 {
102   struct set_entry *entry = (struct set_entry *)id;
103
104   return (const char *)entry->dptr;
105 }
106
107 /**
108  * Returns the length of the string represented by an ident.
109  *
110  * @param handle   the handle for the set
111  * @param id       the ident
112  *
113  * Default implementation using libfirm sets.
114  */
115 static int set_get_id_strlen(void *handle, ident *id)
116 {
117   struct set_entry *entry = (struct set_entry *)id;
118
119   return entry->size;
120 }
121
122 /**
123  * Default implementation using libfirm sets.
124  */
125 void set_finish_ident(void *handle) {
126   set *id_set = handle;
127
128   del_set(id_set);
129 }
130
131 /**
132  * Default implementation if no new_id_from_str() is provided.
133  */
134 static ident *def_new_id_from_str(void *handle, const char *str)
135 {
136   return impl.new_id_from_chars(handle, str, strlen(str));
137 }
138
139 /**
140  * Default implementation if no get_id_strlen() is provided.
141  */
142 static int def_get_id_strlen(void *handle, ident *id)
143 {
144   return strlen(impl.get_id_str(handle, id));
145 }
146
147 #ifdef FIRM_ENABLE_WCHAR
148 /**
149  * Stores a wide character string in the ident module and returns a
150  * handle for the string.
151  *
152  * @param handle   the handle for the set
153  * @param wstr     the wide character string which shall be stored
154  * @param len      length of wstr
155  *
156  * @return id - a handle for the generated ident
157  *
158  * Default implementation using libfirm sets.
159  */
160 static ident *set_new_id_from_wchars(void *handle, const wchar_t *wstr, int len)
161 {
162   set *id_set = handle;
163   wchar_t *tmp;
164
165   /* can't use hinsert0 here, so copy and add a 0 */
166   tmp = alloca((len + 1) * sizeof(*tmp));
167   memcpy(tmp, wstr, len * sizeof(*tmp));
168   tmp[len] = L'\0';
169
170   return (ident *)set_hinsert(id_set, tmp, (len + 1) * sizeof(wchar_t), ID_HASH(wchar_t, tmp, len));
171 }
172
173 /**
174  * Stores a wide character string in the ident module and
175  * returns a handle for the string.
176  *
177  * @param handle   the handle for the set
178  * @param wstr     the wide character string which shall be stored
179  *
180  * Default implementation using libfirm sets.
181  */
182 static ident *set_new_id_from_wcs(void *handle, const wchar_t *wstr)
183 {
184   assert(wstr);
185   return (ident *)set_new_id_from_wchars(handle, wstr, wcslen(wstr));
186 }
187
188 /**
189  * Returns a wide character string represented by an ident.
190  *
191  * @param handle   the handle for the set
192  * @param id       the ident
193  *
194  * Default implementation using libfirm sets.
195  */
196 static const wchar_t *set_get_id_wcs(void *handle, ident *id)
197 {
198   struct set_entry *entry = (struct set_entry *)id;
199
200   return (const wchar_t *)entry->dptr;
201 }
202
203 /**
204  * Returns the length of the string represented by an ident.
205  *
206  * @param handle   the handle for the set
207  * @param id       the ident
208  *
209  * Default implementation using libfirm sets.
210  */
211 static int set_get_id_wcslen(void *handle, ident *id)
212 {
213   struct set_entry *entry = (struct set_entry *)id;
214
215   /* len + \0 is stored for wchar_t */
216   return entry->size / sizeof(wchar_t) - 1;
217 }
218
219 /**
220  * Default implementation if no new_id_from_wcs() is provided.
221  */
222 static ident *def_new_id_from_wcs(void *handle, const wchar_t *wstr)
223 {
224   return impl.new_id_from_wchars(handle, wstr, wcslen(wstr));
225 }
226
227 /**
228  * Default implementation if no new_id_from_wchars() is provided.
229  */
230 static ident *def_new_id_from_wchars(void *handle, const wchar_t *wstr, int len)
231 {
232   return impl.new_id_from_chars(handle, (const char *)wstr, (len + 1) * sizeof(wchar_t));
233 }
234
235 /**
236  * Default implementation if no get_id_wcs() is provided.
237  */
238 static const wchar_t *def_get_id_wcs(void *handle, ident *id)
239 {
240   return (const wchar_t *)impl.get_id_str(handle, id);
241 }
242
243 /**
244  * Default implementation if no get_id_wcslen() is provided.
245  */
246 static int def_get_id_wcslen(void *handle, ident *id)
247 {
248   return wcslen(impl.get_id_wcs(handle, id));
249 }
250 #endif /* FIRM_ENABLE_WCHAR */
251
252 /* Initialize the ident module. */
253 void init_ident(ident_if_t *id_if, int initial_n_idents)
254 {
255   if (id_if) {
256     memcpy(&impl, id_if, sizeof(impl));
257
258     if (! impl.new_id_from_str)
259       impl.new_id_from_str = def_new_id_from_str;
260     if (! impl.get_id_strlen)
261       impl.get_id_strlen = def_get_id_strlen;
262
263 #ifdef FIRM_ENABLE_WCHAR
264     if (! impl.new_id_from_wcs)
265       impl.new_id_from_wcs = def_new_id_from_wcs;
266     if (! impl.new_id_from_wchars)
267       impl.new_id_from_wchars = def_new_id_from_wchars;
268     if (! impl.get_id_wcs)
269       impl.get_id_wcs = def_get_id_wcs;
270     if (! impl.get_id_wcslen)
271       impl.get_id_wcslen = def_get_id_wcslen;
272 #endif /* FIRM_ENABLE_WCHAR */
273   }
274   else {
275    impl.new_id_from_str    = set_new_id_from_str;
276    impl.new_id_from_chars  = set_new_id_from_chars;
277    impl.get_id_str         = set_get_id_str;
278    impl.get_id_strlen      = set_get_id_strlen;
279    impl.finish_ident       = set_finish_ident;
280 #ifdef FIRM_ENABLE_WCHAR
281    impl.new_id_from_wcs    = set_new_id_from_wcs;
282    impl.new_id_from_wchars = set_new_id_from_wchars;
283    impl.get_id_wcs         = set_get_id_wcs;
284    impl.get_id_wcslen      = set_get_id_wcslen;
285 #endif /* FIRM_ENABLE_WCHAR */
286
287    impl.handle = new_set(memcmp, initial_n_idents);
288   }
289 }
290
291 ident *new_id_from_str(const char *str)
292 {
293   assert(str);
294   return impl.new_id_from_str(impl.handle, str);
295 }
296
297 ident *new_id_from_chars(const char *str, int len)
298 {
299   assert(len > 0);
300   return impl.new_id_from_chars(impl.handle, str, len);
301 }
302
303 const char *get_id_str(ident *id)
304 {
305   return impl.get_id_str(impl.handle, id);
306 }
307
308 int get_id_strlen(ident *id)
309 {
310   return impl.get_id_strlen(impl.handle, id);
311 }
312
313 void finish_ident(void) {
314   if (impl.finish_ident)
315     impl.finish_ident(impl.handle);
316 }
317
318 int id_is_prefix(ident *prefix, ident *id)
319 {
320   if (get_id_strlen(prefix) > get_id_strlen(id)) return 0;
321   return 0 == memcmp(get_id_str(prefix), get_id_str(id), get_id_strlen(prefix));
322 }
323
324 int id_is_suffix(ident *suffix, ident *id)
325 {
326   int suflen = get_id_strlen(suffix);
327   int idlen  = get_id_strlen(id);
328   const char *part;
329
330   if (suflen > idlen) return 0;
331
332   part = get_id_str(id);
333   part = part + (idlen - suflen);
334
335   return 0 == memcmp(get_id_str(suffix), part, suflen);
336 }
337
338 int id_contains_char(ident *id, char c)
339 {
340   return strchr(get_id_str(id), c) != NULL;
341 }
342
343 #ifdef FIRM_ENABLE_WCHAR
344
345 ident *new_id_from_wcs (const wchar_t *str)
346 {
347   assert(str);
348   return impl.new_id_from_wcs(impl.handle, str);
349 }
350
351 ident *new_id_from_wchars (const wchar_t *str, int len)
352 {
353   assert(len > 0);
354   return impl.new_id_from_wchars(impl.handle, str, len);
355 }
356
357 const wchar_t *get_id_wcs(ident *id)
358 {
359   return impl.get_id_wcs(impl.handle, id);
360 }
361
362 int  get_id_wcslen(ident *id)
363 {
364   return impl.get_id_wcslen(impl.handle, id);
365 }
366
367 int id_contains_wchar (ident *id, wchar_t c)
368 {
369   return wcschr(get_id_wcs(id), c) != NULL;
370 }
371
372 #endif /* FIRM_ENABLE_WCHAR */