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