3a4e38dd20f933d41018822ba3394518f7d92fae
[libfirm] / 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 #include "ident_t.h"
38 #include "set.h"
39 #include "xmalloc.h"
40
41 /* for debugging only, not the real implementation */
42 struct _ident {
43   char reserved[sizeof(unsigned) + sizeof(size_t)];
44   char data[1];
45 };
46
47 /** The current ident module implementation. */
48 static ident_if_t impl;
49
50 /**
51  * Stores a string in the ident module and returns a handle for the string.
52  *
53  * @param handle   the handle for the set
54  * @param str      the string which shall be stored
55  * @param len      length of str in bytes
56  *
57  * @return id - a handle for the generated ident
58  *
59  * Default implementation using libfirm sets.
60  */
61 static ident *set_new_id_from_chars(void *handle, const char *str, int len)
62 {
63   set *id_set = handle;
64
65   /* GL: Who added this assert?  And why? */
66   //assert(len > 0);
67   return (ident *)set_hinsert0(id_set, str, len, ID_HASH(unsigned char, str, len));
68 }
69
70 /**
71  * Stores a string in the ident module and returns a handle for the string.
72  *
73  * @param handle   the handle for the set
74  * @param str      the string (or whatever) which shall be stored
75  *
76  * Default implementation using libfirm sets.
77  */
78 static ident *set_new_id_from_str(void *handle, const char *str)
79 {
80   assert(str);
81   return (ident *)set_new_id_from_chars(handle, str, strlen(str));
82 }
83
84 /**
85  * Returns a string represented by an ident.
86  *
87  * @param handle   the handle for the set
88  * @param id       the ident
89  *
90  * Default implementation using libfirm sets.
91  */
92 static const char *set_get_id_str(void *handle, ident *id)
93 {
94   struct set_entry *entry = (struct set_entry *)id;
95   (void) handle;
96
97   return (const char *)entry->dptr;
98 }
99
100 /**
101  * Returns the length of the string represented by an ident.
102  *
103  * @param handle   the handle for the set
104  * @param id       the ident
105  *
106  * Default implementation using libfirm sets.
107  */
108 static int set_get_id_strlen(void *handle, ident *id)
109 {
110   struct set_entry *entry = (struct set_entry *)id;
111   (void) handle;
112
113   return entry->size;
114 }
115
116 /**
117  * Default implementation using libfirm sets.
118  */
119 void set_finish_ident(void *handle) {
120   set *id_set = handle;
121
122   del_set(id_set);
123 }
124
125 /**
126  * Default implementation if no new_id_from_str() is provided.
127  */
128 static ident *def_new_id_from_str(void *handle, const char *str)
129 {
130   return impl.new_id_from_chars(handle, str, strlen(str));
131 }
132
133 /**
134  * Default implementation if no get_id_strlen() is provided.
135  */
136 static int def_get_id_strlen(void *handle, ident *id)
137 {
138   return strlen(impl.get_id_str(handle, id));
139 }
140
141 /* Initialize the ident module. */
142 void init_ident(ident_if_t *id_if, int initial_n_idents)
143 {
144   if (id_if) {
145     memcpy(&impl, id_if, sizeof(impl));
146
147     if (! impl.new_id_from_str)
148       impl.new_id_from_str = def_new_id_from_str;
149     if (! impl.get_id_strlen)
150       impl.get_id_strlen = def_get_id_strlen;
151   } else {
152    impl.new_id_from_str    = set_new_id_from_str;
153    impl.new_id_from_chars  = set_new_id_from_chars;
154    impl.get_id_str         = set_get_id_str;
155    impl.get_id_strlen      = set_get_id_strlen;
156    impl.finish_ident       = set_finish_ident;
157
158    /* it's ok to use memcmp here, we check only strings */
159    impl.handle = new_set(memcmp, initial_n_idents);
160   }
161 }
162
163 ident *new_id_from_str(const char *str)
164 {
165   assert(str);
166   return impl.new_id_from_str(impl.handle, str);
167 }
168
169 ident *new_id_from_chars(const char *str, int len)
170 {
171   assert(len > 0);
172   return impl.new_id_from_chars(impl.handle, str, len);
173 }
174
175 const char *get_id_str(ident *id)
176 {
177   return impl.get_id_str(impl.handle, id);
178 }
179
180 int get_id_strlen(ident *id)
181 {
182   return impl.get_id_strlen(impl.handle, id);
183 }
184
185 void finish_ident(void) {
186   if (impl.finish_ident)
187     impl.finish_ident(impl.handle);
188 }
189
190 int id_is_prefix(ident *prefix, ident *id)
191 {
192   if (get_id_strlen(prefix) > get_id_strlen(id)) return 0;
193   return 0 == memcmp(get_id_str(prefix), get_id_str(id), get_id_strlen(prefix));
194 }
195
196 int id_is_suffix(ident *suffix, ident *id)
197 {
198   int suflen = get_id_strlen(suffix);
199   int idlen  = get_id_strlen(id);
200   const char *part;
201
202   if (suflen > idlen) return 0;
203
204   part = get_id_str(id);
205   part = part + (idlen - suflen);
206
207   return 0 == memcmp(get_id_str(suffix), part, suflen);
208 }
209
210 int id_contains_char(ident *id, char c)
211 {
212   return strchr(get_id_str(id), c) != NULL;
213 }
214
215 ident *id_unique(const char *tag)
216 {
217         static unsigned unique_id = 0;
218         char buf[256];
219
220         snprintf(buf, sizeof(buf), tag, unique_id);
221         unique_id++;
222         return new_id_from_str(buf);
223 }