OSDN Git Service

* objc/encoding.c (objc_sizeof_type): Should assign from ROUND,
[pf3gnuchains/gcc-fork.git] / gcc / objc / selector.c
1 /* GNU Objective C Runtime selector related functions
2    Copyright (C) 1993 Free Software Foundation, Inc.
3
4 Author: Kresten Krab Thorup
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify it under the
9    terms of the GNU General Public License as published by the Free Software
10    Foundation; either version 2, or (at your option) any later version.
11
12 GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15    details.
16
17 You should have received a copy of the GNU General Public License along with
18    GNU CC; see the file COPYING.  If not, write to the Free Software
19    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* As a special exception, if you link this library with files compiled with
22    GCC to produce an executable, this does not cause the resulting executable
23    to be covered by the GNU General Public License. This exception does not
24    however invalidate any other reasons why the executable file might be
25    covered by the GNU General Public License.  */
26
27 #include "runtime.h"
28 #include "objc/sarray.h"
29 #include "encoding.h"
30
31 /* Initial selector hash table size. Value doesnt matter much */
32 #define SELECTOR_HASH_SIZE 128
33
34 /* Tables mapping selector names to uid and opposite */
35 static struct sarray* __objc_selector_array = 0; /* uid -> sel */
36 static struct sarray* __objc_selector_names = 0; /* uid -> name */
37 static cache_ptr      __objc_selector_hash  = 0; /* name -> uid */
38
39 static void register_selectors_from_list(MethodList_t);
40
41 /* Number of selectors stored in each of the above tables */
42 int __objc_selector_max_index = 0;
43
44 void __objc_init_selector_tables()
45 {
46   __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
47   __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
48   __objc_selector_hash
49     = hash_new (SELECTOR_HASH_SIZE,
50                 (hash_func_type) hash_string,
51                 (compare_func_type) compare_strings);
52 }  
53
54 /* This routine is given a class and records all of the methods in its class
55    structure in the record table.  */
56 void
57 __objc_register_selectors_from_class (Class* class)
58 {
59   MethodList_t method_list;
60
61   method_list = class->methods;
62   while (method_list)
63     {
64       register_selectors_from_list (method_list);
65       method_list = method_list->method_next;
66     }
67 }
68
69
70 /* This routine is given a list of methods and records each of the methods in
71    the record table.  This is the routine that does the actual recording
72    work.
73
74    This one is only called for Class objects.  For categories,
75    class_add_method_list is called.
76    */
77 static void
78 register_selectors_from_list (MethodList_t method_list)
79 {
80   int i = 0;
81   while (i < method_list->method_count)
82     {
83       Method_t method = &method_list->method_list[i];
84       method->method_name 
85         = sel_register_typed_name ((const char*)method->method_name, 
86                                      method->method_types);
87       i += 1;
88     }
89 }
90
91
92 /* Returns YES iff t1 and t2 have same method types, but we ignore
93    the argframe layout */
94 BOOL
95 sel_types_match (const char* t1, const char* t2)
96 {
97   if (!t1 || !t2)
98     return NO;
99   while (*t1 && *t2)
100     {
101       if (*t1 == '+') t1++;
102       if (*t2 == '+') t2++;
103       while (isdigit(*t1)) t1++;
104       while (isdigit(*t2)) t2++;
105       /* xxx Remove these next two lines when qualifiers are put in
106          all selectors, not just Protocol selectors. */
107       t1 = objc_skip_type_qualifiers(t1);
108       t2 = objc_skip_type_qualifiers(t2);
109       if (!*t1 && !*t2)
110         return YES;
111       if (*t1 != *t2)
112         return NO;
113       t1++;
114       t2++;
115     }
116   return NO;
117 }
118
119 /* return selector representing name */
120 SEL
121 sel_get_typed_uid (const char *name, const char *types)
122 {
123   struct objc_list *l;
124   sidx i;
125
126   i = (sidx) hash_value_for_key (__objc_selector_hash, name);
127   if (i == 0)
128     return 0;
129
130   for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
131        l; l = l->tail)
132     {
133       SEL s = (SEL)l->head;
134       if (types == 0 || s->sel_types == 0)
135         {
136           if (s->sel_types == types)
137             {
138               return s;
139             }
140         }
141       else if (sel_types_match (s->sel_types, types))
142         {
143           return s;
144         }
145     }
146
147   return 0;
148 }
149
150 /* return selector representing name */
151 SEL
152 sel_get_any_uid (const char *name)
153 {
154   struct objc_list *l;
155   sidx i;
156
157   i = (sidx) hash_value_for_key (__objc_selector_hash, name);
158   if (soffset_decode (i) == 0)
159     return 0;
160
161   l = (struct objc_list*)sarray_get (__objc_selector_array, i);
162   if (l == 0)
163     return 0;
164
165   return (SEL)l->head;
166 }
167
168 /* return selector representing name */
169 SEL
170 sel_get_uid (const char *name)
171 {
172   return sel_register_typed_name (name, 0);
173 }
174
175 /* Get name of selector.  If selector is unknown, the empty string "" 
176    is returned */ 
177 const char*
178 sel_get_name (SEL selector)
179 {
180   if ((soffset_decode((sidx)selector->sel_id) > 0)
181       && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index))
182     return sarray_get (__objc_selector_names, (sidx) selector->sel_id);
183   else
184     return 0;
185 }
186
187 BOOL
188 sel_is_mapped (SEL selector)
189 {
190   unsigned int idx = soffset_decode ((sidx)selector->sel_id);
191   return ((idx > 0) && (idx <= __objc_selector_max_index));
192 }
193
194
195 const char*
196 sel_get_type (SEL selector)
197 {
198   if (selector)
199     return selector->sel_types;
200   else
201     return 0;
202 }
203
204 /* The uninstalled dispatch table */
205 extern struct sarray* __objc_uninstalled_dtable;
206
207 /* Store the passed selector name in the selector record and return its
208    selector value (value returned by sel_get_uid). */
209 SEL
210 __sel_register_typed_name (const char *name, const char *types, 
211                            struct objc_selector *orig)
212 {
213   struct objc_selector* j;
214   sidx i;
215   struct objc_list *l;
216
217   i = (sidx) hash_value_for_key (__objc_selector_hash, name);
218   if (soffset_decode (i) != 0)
219     {
220       for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
221            l; l = l->tail)
222         {
223           SEL s = (SEL)l->head;
224           if (types == 0 || s->sel_types == 0)
225             {
226               if (s->sel_types == types)
227                 {
228                   if (orig)
229                     {
230                       orig->sel_id = (void*)i;
231                       return orig;
232                     }
233                   else
234                     return s;
235                 }
236             }
237           else if (!strcmp (s->sel_types, types))
238             {
239               if (orig)
240                 {
241                   orig->sel_id = (void*)i;
242                   return orig;
243                 }
244               else
245                 return s;
246             }
247         }
248       if (orig)
249         j = orig;
250       else
251         j = __objc_xmalloc (sizeof (struct objc_selector));
252
253       j->sel_id = (void*)i;
254       j->sel_types = (const char*)types;
255       l = (struct objc_list*)sarray_get (__objc_selector_array, i);
256     }
257   else
258     {
259       __objc_selector_max_index += 1;
260       i = soffset_encode(__objc_selector_max_index);
261       if (orig)
262         j = orig;
263       else
264         j = __objc_xmalloc (sizeof (struct objc_selector));
265         
266       j->sel_id = (void*)i;
267       j->sel_types = (const char*)types;
268       l = 0;
269     }
270
271   DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types, 
272                 soffset_decode (i));
273   
274   {
275     int is_new = (l == 0);
276     l = list_cons ((void*)j, l);
277     sarray_at_put_safe (__objc_selector_names, i, (void *) name);
278     sarray_at_put_safe (__objc_selector_array, i, (void *) l);
279     if (is_new)
280       hash_add (&__objc_selector_hash, (void *) name, (void *) i);
281   }
282
283   sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1);
284
285   return (SEL) j;
286 }
287
288 SEL
289 sel_register_name (const char *name)
290 {
291   return __sel_register_typed_name (name, 0, 0);
292 }
293
294 SEL
295 sel_register_typed_name (const char *name, const char *type)
296 {
297   return __sel_register_typed_name (name, type, 0);
298 }
299