xref: /dflybsd-src/contrib/gcc-4.7/libobjc/protocols.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* GNU Objective C Runtime protocol related functions.
2*e4b17023SJohn Marino    Copyright (C) 2010 Free Software Foundation, Inc.
3*e4b17023SJohn Marino    Contributed by Nicola Pero
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under the
8*e4b17023SJohn Marino terms of the GNU General Public License as published by the Free Software
9*e4b17023SJohn Marino Foundation; either version 3, or (at your option) any later version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13*e4b17023SJohn Marino FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14*e4b17023SJohn Marino details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino #include "objc-private/common.h"
26*e4b17023SJohn Marino #include "objc/runtime.h"
27*e4b17023SJohn Marino #include "objc-private/module-abi-8.h" /* For runtime structures  */
28*e4b17023SJohn Marino #include "objc/thr.h"
29*e4b17023SJohn Marino #include "objc-private/runtime.h"      /* the kitchen sink */
30*e4b17023SJohn Marino #include "objc-private/hash.h"         /* For the hash table of protocols.  */
31*e4b17023SJohn Marino #include "objc-private/protocols.h"    /* For __objc_protocols_init() and
32*e4b17023SJohn Marino                                           __objc_protocols_add_protocol().  */
33*e4b17023SJohn Marino #include <stdlib.h>                    /* For malloc.  */
34*e4b17023SJohn Marino 
35*e4b17023SJohn Marino /* This is a table that maps a name to a Protocol instance with that
36*e4b17023SJohn Marino    name.  Because there may be multiple Protocol instances with the
37*e4b17023SJohn Marino    same name (no harm in that) the table records only one
38*e4b17023SJohn Marino    instance.  */
39*e4b17023SJohn Marino static cache_ptr __protocols_hashtable;
40*e4b17023SJohn Marino 
41*e4b17023SJohn Marino /* A mutex protecting the protocol_hashtable.  */
42*e4b17023SJohn Marino static objc_mutex_t __protocols_hashtable_lock = NULL;
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino /* Called at startup by init.c.  */
45*e4b17023SJohn Marino void
__objc_protocols_init(void)46*e4b17023SJohn Marino __objc_protocols_init (void)
47*e4b17023SJohn Marino {
48*e4b17023SJohn Marino   __protocols_hashtable_lock = objc_mutex_allocate ();
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino   /* The keys in the table are strings, and the values are Protocol
51*e4b17023SJohn Marino      objects.  */
52*e4b17023SJohn Marino   __protocols_hashtable = objc_hash_new (64, (hash_func_type) objc_hash_string,
53*e4b17023SJohn Marino 					 (compare_func_type) objc_compare_strings);
54*e4b17023SJohn Marino }
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino /* Add a protocol to the hashtable.  */
57*e4b17023SJohn Marino void
__objc_protocols_add_protocol(const char * name,struct objc_protocol * object)58*e4b17023SJohn Marino __objc_protocols_add_protocol (const char *name, struct objc_protocol *object)
59*e4b17023SJohn Marino {
60*e4b17023SJohn Marino   objc_mutex_lock (__protocols_hashtable_lock);
61*e4b17023SJohn Marino 
62*e4b17023SJohn Marino   /* If we find a protocol with the same name already in the
63*e4b17023SJohn Marino      hashtable, we do not need to add the new one, because it will be
64*e4b17023SJohn Marino      identical to it.  This in the reasonable assumption that two
65*e4b17023SJohn Marino      protocols with the same name are identical, which is expected in
66*e4b17023SJohn Marino      any sane program.  If we are really paranoid, we would compare
67*e4b17023SJohn Marino      the protocols and abort if they are not identical.
68*e4b17023SJohn Marino      Unfortunately, this would slow down the startup of all
69*e4b17023SJohn Marino      Objective-C programs while trying to catch a problem that has
70*e4b17023SJohn Marino      never been seen in practice, so we don't do it.  */
71*e4b17023SJohn Marino   if (! objc_hash_is_key_in_hash (__protocols_hashtable, name))
72*e4b17023SJohn Marino     objc_hash_add (&__protocols_hashtable, name, object);
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino   objc_mutex_unlock (__protocols_hashtable_lock);
75*e4b17023SJohn Marino }
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino Protocol *
objc_getProtocol(const char * name)78*e4b17023SJohn Marino objc_getProtocol (const char *name)
79*e4b17023SJohn Marino {
80*e4b17023SJohn Marino   Protocol *protocol;
81*e4b17023SJohn Marino 
82*e4b17023SJohn Marino   if (name == NULL)
83*e4b17023SJohn Marino     return NULL;
84*e4b17023SJohn Marino 
85*e4b17023SJohn Marino   objc_mutex_lock (__protocols_hashtable_lock);
86*e4b17023SJohn Marino   protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name));
87*e4b17023SJohn Marino   objc_mutex_unlock (__protocols_hashtable_lock);
88*e4b17023SJohn Marino 
89*e4b17023SJohn Marino   return protocol;
90*e4b17023SJohn Marino }
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino Protocol **
objc_copyProtocolList(unsigned int * numberOfReturnedProtocols)93*e4b17023SJohn Marino objc_copyProtocolList (unsigned int *numberOfReturnedProtocols)
94*e4b17023SJohn Marino {
95*e4b17023SJohn Marino   unsigned int count = 0;
96*e4b17023SJohn Marino   Protocol **returnValue = NULL;
97*e4b17023SJohn Marino   node_ptr node;
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino   objc_mutex_lock (__protocols_hashtable_lock);
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino   /* Count how many protocols we have.  */
102*e4b17023SJohn Marino   node = objc_hash_next (__protocols_hashtable, NULL);
103*e4b17023SJohn Marino   while (node)
104*e4b17023SJohn Marino     {
105*e4b17023SJohn Marino       count++;
106*e4b17023SJohn Marino       node = objc_hash_next (__protocols_hashtable, node);
107*e4b17023SJohn Marino     }
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino   if (count != 0)
110*e4b17023SJohn Marino     {
111*e4b17023SJohn Marino       unsigned int i = 0;
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino       /* Allocate enough memory to hold them.  */
114*e4b17023SJohn Marino       returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
115*e4b17023SJohn Marino 
116*e4b17023SJohn Marino       /* Copy the protocols.  */
117*e4b17023SJohn Marino       node = objc_hash_next (__protocols_hashtable, NULL);
118*e4b17023SJohn Marino       while (node)
119*e4b17023SJohn Marino 	{
120*e4b17023SJohn Marino 	  returnValue[i] = node->value;
121*e4b17023SJohn Marino 	  i++;
122*e4b17023SJohn Marino 	  node = objc_hash_next (__protocols_hashtable, node);
123*e4b17023SJohn Marino 	}
124*e4b17023SJohn Marino 
125*e4b17023SJohn Marino       returnValue[i] = NULL;
126*e4b17023SJohn Marino     }
127*e4b17023SJohn Marino   objc_mutex_unlock (__protocols_hashtable_lock);
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino   if (numberOfReturnedProtocols)
130*e4b17023SJohn Marino     *numberOfReturnedProtocols = count;
131*e4b17023SJohn Marino 
132*e4b17023SJohn Marino   return returnValue;
133*e4b17023SJohn Marino }
134*e4b17023SJohn Marino 
135*e4b17023SJohn Marino BOOL
class_addProtocol(Class class_,Protocol * protocol)136*e4b17023SJohn Marino class_addProtocol (Class class_, Protocol *protocol)
137*e4b17023SJohn Marino {
138*e4b17023SJohn Marino   struct objc_protocol_list *protocols;
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino   if (class_ == Nil  ||  protocol == NULL)
141*e4b17023SJohn Marino     return NO;
142*e4b17023SJohn Marino 
143*e4b17023SJohn Marino   if (class_conformsToProtocol (class_, protocol))
144*e4b17023SJohn Marino     return NO;
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino   /* Check that it is a Protocol object before casting it to (struct
147*e4b17023SJohn Marino      objc_protocol *).  */
148*e4b17023SJohn Marino   if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
149*e4b17023SJohn Marino     return NO;
150*e4b17023SJohn Marino 
151*e4b17023SJohn Marino   objc_mutex_lock (__objc_runtime_mutex);
152*e4b17023SJohn Marino 
153*e4b17023SJohn Marino   /* Create the objc_protocol_list.  */
154*e4b17023SJohn Marino   protocols = malloc (sizeof (struct objc_protocol_list));
155*e4b17023SJohn Marino   protocols->count = 1;
156*e4b17023SJohn Marino   protocols->list[0] = (struct objc_protocol *)protocol;
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino   /* Attach it to the list of class protocols.  */
159*e4b17023SJohn Marino   protocols->next = class_->protocols;
160*e4b17023SJohn Marino   class_->protocols = protocols;
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino   objc_mutex_unlock (__objc_runtime_mutex);
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino   return YES;
165*e4b17023SJohn Marino }
166*e4b17023SJohn Marino 
167*e4b17023SJohn Marino BOOL
class_conformsToProtocol(Class class_,Protocol * protocol)168*e4b17023SJohn Marino class_conformsToProtocol (Class class_, Protocol *protocol)
169*e4b17023SJohn Marino {
170*e4b17023SJohn Marino   struct objc_protocol_list* proto_list;
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino   if (class_ == Nil  ||  protocol == NULL)
173*e4b17023SJohn Marino     return NO;
174*e4b17023SJohn Marino 
175*e4b17023SJohn Marino   /* Check that it is a Protocol object before casting it to (struct
176*e4b17023SJohn Marino      objc_protocol *).  */
177*e4b17023SJohn Marino   if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
178*e4b17023SJohn Marino     return NO;
179*e4b17023SJohn Marino 
180*e4b17023SJohn Marino   /* Acquire the runtime lock because the list of protocols for a
181*e4b17023SJohn Marino      class may be modified concurrently, for example if another thread
182*e4b17023SJohn Marino      calls class_addProtocol(), or dynamically loads from a file a
183*e4b17023SJohn Marino      category of the class.  */
184*e4b17023SJohn Marino   objc_mutex_lock (__objc_runtime_mutex);
185*e4b17023SJohn Marino   proto_list = class_->protocols;
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino   while (proto_list)
188*e4b17023SJohn Marino     {
189*e4b17023SJohn Marino       size_t i;
190*e4b17023SJohn Marino       for (i = 0; i < proto_list->count; i++)
191*e4b17023SJohn Marino 	{
192*e4b17023SJohn Marino 	  if (proto_list->list[i] == (struct objc_protocol *)protocol
193*e4b17023SJohn Marino 	      || protocol_conformsToProtocol ((Protocol *)proto_list->list[i],
194*e4b17023SJohn Marino 					      protocol))
195*e4b17023SJohn Marino 	    {
196*e4b17023SJohn Marino 	      objc_mutex_unlock (__objc_runtime_mutex);
197*e4b17023SJohn Marino 	      return YES;
198*e4b17023SJohn Marino 	    }
199*e4b17023SJohn Marino 	}
200*e4b17023SJohn Marino       proto_list = proto_list->next;
201*e4b17023SJohn Marino     }
202*e4b17023SJohn Marino 
203*e4b17023SJohn Marino   objc_mutex_unlock (__objc_runtime_mutex);
204*e4b17023SJohn Marino   return NO;
205*e4b17023SJohn Marino }
206*e4b17023SJohn Marino 
207*e4b17023SJohn Marino Protocol **
class_copyProtocolList(Class class_,unsigned int * numberOfReturnedProtocols)208*e4b17023SJohn Marino class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
209*e4b17023SJohn Marino {
210*e4b17023SJohn Marino   unsigned int count = 0;
211*e4b17023SJohn Marino   Protocol **returnValue = NULL;
212*e4b17023SJohn Marino   struct objc_protocol_list* proto_list;
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino   if (class_ == Nil)
215*e4b17023SJohn Marino     {
216*e4b17023SJohn Marino       if (numberOfReturnedProtocols)
217*e4b17023SJohn Marino 	*numberOfReturnedProtocols = 0;
218*e4b17023SJohn Marino       return NULL;
219*e4b17023SJohn Marino     }
220*e4b17023SJohn Marino 
221*e4b17023SJohn Marino   /* Lock the runtime mutex because the class protocols may be
222*e4b17023SJohn Marino      concurrently modified.  */
223*e4b17023SJohn Marino   objc_mutex_lock (__objc_runtime_mutex);
224*e4b17023SJohn Marino 
225*e4b17023SJohn Marino   /* Count how many protocols we have.  */
226*e4b17023SJohn Marino   proto_list = class_->protocols;
227*e4b17023SJohn Marino 
228*e4b17023SJohn Marino   while (proto_list)
229*e4b17023SJohn Marino     {
230*e4b17023SJohn Marino       count = count + proto_list->count;
231*e4b17023SJohn Marino       proto_list = proto_list->next;
232*e4b17023SJohn Marino     }
233*e4b17023SJohn Marino 
234*e4b17023SJohn Marino   if (count != 0)
235*e4b17023SJohn Marino     {
236*e4b17023SJohn Marino       unsigned int i = 0;
237*e4b17023SJohn Marino 
238*e4b17023SJohn Marino       /* Allocate enough memory to hold them.  */
239*e4b17023SJohn Marino       returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
240*e4b17023SJohn Marino 
241*e4b17023SJohn Marino       /* Copy the protocols.  */
242*e4b17023SJohn Marino       proto_list = class_->protocols;
243*e4b17023SJohn Marino 
244*e4b17023SJohn Marino       while (proto_list)
245*e4b17023SJohn Marino 	{
246*e4b17023SJohn Marino 	  size_t j;
247*e4b17023SJohn Marino 	  for (j = 0; j < proto_list->count; j++)
248*e4b17023SJohn Marino 	    {
249*e4b17023SJohn Marino 	      returnValue[i] = (Protocol *)proto_list->list[j];
250*e4b17023SJohn Marino 	      i++;
251*e4b17023SJohn Marino 	    }
252*e4b17023SJohn Marino 	  proto_list = proto_list->next;
253*e4b17023SJohn Marino 	}
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino       returnValue[i] = NULL;
256*e4b17023SJohn Marino     }
257*e4b17023SJohn Marino   objc_mutex_unlock (__objc_runtime_mutex);
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino   if (numberOfReturnedProtocols)
260*e4b17023SJohn Marino     *numberOfReturnedProtocols = count;
261*e4b17023SJohn Marino 
262*e4b17023SJohn Marino   return returnValue;
263*e4b17023SJohn Marino }
264*e4b17023SJohn Marino 
265*e4b17023SJohn Marino BOOL
protocol_conformsToProtocol(Protocol * protocol,Protocol * anotherProtocol)266*e4b17023SJohn Marino protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol)
267*e4b17023SJohn Marino {
268*e4b17023SJohn Marino   struct objc_protocol_list* proto_list;
269*e4b17023SJohn Marino 
270*e4b17023SJohn Marino   if (protocol == NULL  ||  anotherProtocol == NULL)
271*e4b17023SJohn Marino     return NO;
272*e4b17023SJohn Marino 
273*e4b17023SJohn Marino   if (protocol == anotherProtocol)
274*e4b17023SJohn Marino     return YES;
275*e4b17023SJohn Marino 
276*e4b17023SJohn Marino   /* Check that the objects are Protocol objects before casting them
277*e4b17023SJohn Marino      to (struct objc_protocol *).  */
278*e4b17023SJohn Marino   if (protocol->class_pointer != anotherProtocol->class_pointer)
279*e4b17023SJohn Marino     return NO;
280*e4b17023SJohn Marino 
281*e4b17023SJohn Marino   if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
282*e4b17023SJohn Marino     return NO;
283*e4b17023SJohn Marino 
284*e4b17023SJohn Marino   if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
285*e4b17023SJohn Marino 	      ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
286*e4b17023SJohn Marino     return YES;
287*e4b17023SJohn Marino 
288*e4b17023SJohn Marino   /* We do not acquire any lock because protocols are currently
289*e4b17023SJohn Marino      immutable.  We can freely iterate over a protocol structure.  */
290*e4b17023SJohn Marino   proto_list = ((struct objc_protocol *)protocol)->protocol_list;
291*e4b17023SJohn Marino   while (proto_list)
292*e4b17023SJohn Marino     {
293*e4b17023SJohn Marino       size_t i;
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino       for (i = 0; i < proto_list->count; i++)
296*e4b17023SJohn Marino 	{
297*e4b17023SJohn Marino 	  if (protocol_conformsToProtocol ((Protocol *)proto_list->list[i], anotherProtocol))
298*e4b17023SJohn Marino 	    return YES;
299*e4b17023SJohn Marino 	}
300*e4b17023SJohn Marino       proto_list = proto_list->next;
301*e4b17023SJohn Marino     }
302*e4b17023SJohn Marino 
303*e4b17023SJohn Marino   return NO;
304*e4b17023SJohn Marino }
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino BOOL
protocol_isEqual(Protocol * protocol,Protocol * anotherProtocol)307*e4b17023SJohn Marino protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol)
308*e4b17023SJohn Marino {
309*e4b17023SJohn Marino   if (protocol == anotherProtocol)
310*e4b17023SJohn Marino     return YES;
311*e4b17023SJohn Marino 
312*e4b17023SJohn Marino   if (protocol == NULL  ||  anotherProtocol == NULL)
313*e4b17023SJohn Marino     return NO;
314*e4b17023SJohn Marino 
315*e4b17023SJohn Marino   /* Check that the objects are Protocol objects before casting them
316*e4b17023SJohn Marino      to (struct objc_protocol *).  */
317*e4b17023SJohn Marino   if (protocol->class_pointer != anotherProtocol->class_pointer)
318*e4b17023SJohn Marino     return NO;
319*e4b17023SJohn Marino 
320*e4b17023SJohn Marino   if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
321*e4b17023SJohn Marino     return NO;
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino   /* Equality between formal protocols is only formal (nothing to do
324*e4b17023SJohn Marino      with actually checking the list of methods they have!).  Two
325*e4b17023SJohn Marino      formal Protocols are equal if and only if they have the same
326*e4b17023SJohn Marino      name.
327*e4b17023SJohn Marino 
328*e4b17023SJohn Marino      Please note (for comparisons with other implementations) that
329*e4b17023SJohn Marino      checking the names is equivalent to checking that Protocol A
330*e4b17023SJohn Marino      conforms to Protocol B and Protocol B conforms to Protocol A,
331*e4b17023SJohn Marino      because this happens iff they have the same name.  If they have
332*e4b17023SJohn Marino      different names, A conforms to B if and only if A includes B, but
333*e4b17023SJohn Marino      the situation where A includes B and B includes A is a circular
334*e4b17023SJohn Marino      dependency between Protocols which is forbidden by the compiler,
335*e4b17023SJohn Marino      so A conforms to B and B conforms to A with A and B having
336*e4b17023SJohn Marino      different names is an impossible case.  */
337*e4b17023SJohn Marino   if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
338*e4b17023SJohn Marino 	      ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
339*e4b17023SJohn Marino     return YES;
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino   return NO;
342*e4b17023SJohn Marino }
343*e4b17023SJohn Marino 
344*e4b17023SJohn Marino const char *
protocol_getName(Protocol * protocol)345*e4b17023SJohn Marino protocol_getName (Protocol *protocol)
346*e4b17023SJohn Marino {
347*e4b17023SJohn Marino   /* Check that it is a Protocol object before casting it to (struct
348*e4b17023SJohn Marino      objc_protocol *).  */
349*e4b17023SJohn Marino   if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
350*e4b17023SJohn Marino     return NULL;
351*e4b17023SJohn Marino 
352*e4b17023SJohn Marino   return ((struct objc_protocol *)protocol)->protocol_name;
353*e4b17023SJohn Marino }
354*e4b17023SJohn Marino 
protocol_getMethodDescription(Protocol * protocol,SEL selector,BOOL requiredMethod,BOOL instanceMethod)355*e4b17023SJohn Marino struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
356*e4b17023SJohn Marino 							      SEL selector,
357*e4b17023SJohn Marino 							      BOOL requiredMethod,
358*e4b17023SJohn Marino 							      BOOL instanceMethod)
359*e4b17023SJohn Marino {
360*e4b17023SJohn Marino   struct objc_method_description no_result = { NULL, NULL };
361*e4b17023SJohn Marino   struct objc_method_description_list *methods;
362*e4b17023SJohn Marino   int i;
363*e4b17023SJohn Marino 
364*e4b17023SJohn Marino   /* TODO: New ABI.  */
365*e4b17023SJohn Marino   /* The current ABI does not have any information on optional protocol methods.  */
366*e4b17023SJohn Marino   if (! requiredMethod)
367*e4b17023SJohn Marino     return no_result;
368*e4b17023SJohn Marino 
369*e4b17023SJohn Marino   /* Check that it is a Protocol object before casting it to (struct
370*e4b17023SJohn Marino      objc_protocol *).  */
371*e4b17023SJohn Marino   if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
372*e4b17023SJohn Marino     return no_result;
373*e4b17023SJohn Marino 
374*e4b17023SJohn Marino   if (instanceMethod)
375*e4b17023SJohn Marino     methods = ((struct objc_protocol *)protocol)->instance_methods;
376*e4b17023SJohn Marino   else
377*e4b17023SJohn Marino     methods = ((struct objc_protocol *)protocol)->class_methods;
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino   if (methods)
380*e4b17023SJohn Marino     {
381*e4b17023SJohn Marino       for (i = 0; i < methods->count; i++)
382*e4b17023SJohn Marino 	{
383*e4b17023SJohn Marino 	  if (sel_isEqual (methods->list[i].name, selector))
384*e4b17023SJohn Marino 	    return methods->list[i];
385*e4b17023SJohn Marino 	  /*
386*e4b17023SJohn Marino 	  if (strcmp (sel_getName (methods->list[i].name), selector_name) == 0)
387*e4b17023SJohn Marino 	    return methods->list[i];
388*e4b17023SJohn Marino 	  */
389*e4b17023SJohn Marino 	}
390*e4b17023SJohn Marino     }
391*e4b17023SJohn Marino 
392*e4b17023SJohn Marino   return no_result;
393*e4b17023SJohn Marino }
394*e4b17023SJohn Marino 
protocol_copyMethodDescriptionList(Protocol * protocol,BOOL requiredMethod,BOOL instanceMethod,unsigned int * numberOfReturnedMethods)395*e4b17023SJohn Marino struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
396*e4b17023SJohn Marino 								    BOOL requiredMethod,
397*e4b17023SJohn Marino 								    BOOL instanceMethod,
398*e4b17023SJohn Marino 								    unsigned int *numberOfReturnedMethods)
399*e4b17023SJohn Marino {
400*e4b17023SJohn Marino   struct objc_method_description_list *methods;
401*e4b17023SJohn Marino   unsigned int count = 0;
402*e4b17023SJohn Marino   struct objc_method_description *returnValue = NULL;
403*e4b17023SJohn Marino 
404*e4b17023SJohn Marino   /* TODO: New ABI */
405*e4b17023SJohn Marino   /* The current ABI does not have any information on optional protocol methods.  */
406*e4b17023SJohn Marino   if (! requiredMethod)
407*e4b17023SJohn Marino     {
408*e4b17023SJohn Marino       if (numberOfReturnedMethods)
409*e4b17023SJohn Marino 	*numberOfReturnedMethods = 0;
410*e4b17023SJohn Marino 
411*e4b17023SJohn Marino       return NULL;
412*e4b17023SJohn Marino     }
413*e4b17023SJohn Marino 
414*e4b17023SJohn Marino   /* Check that it is a Protocol object before casting it to (struct
415*e4b17023SJohn Marino      objc_protocol *).  */
416*e4b17023SJohn Marino   if (protocol == NULL  ||  protocol->class_pointer != objc_lookUpClass ("Protocol"))
417*e4b17023SJohn Marino     {
418*e4b17023SJohn Marino       if (numberOfReturnedMethods)
419*e4b17023SJohn Marino 	*numberOfReturnedMethods = 0;
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino       return NULL;
422*e4b17023SJohn Marino     }
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino   /* We do not acquire any lock because protocols are currently
425*e4b17023SJohn Marino      immutable.  We can freely iterate over a protocol structure.  */
426*e4b17023SJohn Marino 
427*e4b17023SJohn Marino   if (instanceMethod)
428*e4b17023SJohn Marino     methods = ((struct objc_protocol *)protocol)->instance_methods;
429*e4b17023SJohn Marino   else
430*e4b17023SJohn Marino     methods = ((struct objc_protocol *)protocol)->class_methods;
431*e4b17023SJohn Marino 
432*e4b17023SJohn Marino   if (methods)
433*e4b17023SJohn Marino     {
434*e4b17023SJohn Marino       unsigned int i;
435*e4b17023SJohn Marino       count = methods->count;
436*e4b17023SJohn Marino 
437*e4b17023SJohn Marino       /* Allocate enough memory to hold them.  */
438*e4b17023SJohn Marino       returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1)));
439*e4b17023SJohn Marino 
440*e4b17023SJohn Marino       /* Copy them.  */
441*e4b17023SJohn Marino       for (i = 0; i < count; i++)
442*e4b17023SJohn Marino 	{
443*e4b17023SJohn Marino 	  returnValue[i].name = methods->list[i].name;
444*e4b17023SJohn Marino 	  returnValue[i].types = methods->list[i].types;
445*e4b17023SJohn Marino 	}
446*e4b17023SJohn Marino       returnValue[i].name = NULL;
447*e4b17023SJohn Marino       returnValue[i].types = NULL;
448*e4b17023SJohn Marino     }
449*e4b17023SJohn Marino 
450*e4b17023SJohn Marino   if (numberOfReturnedMethods)
451*e4b17023SJohn Marino     *numberOfReturnedMethods = count;
452*e4b17023SJohn Marino 
453*e4b17023SJohn Marino   return returnValue;
454*e4b17023SJohn Marino }
455*e4b17023SJohn Marino 
protocol_getProperty(Protocol * protocol,const char * propertyName,BOOL requiredProperty,BOOL instanceProperty)456*e4b17023SJohn Marino Property protocol_getProperty (Protocol *protocol, const char *propertyName,
457*e4b17023SJohn Marino 			       BOOL requiredProperty, BOOL instanceProperty)
458*e4b17023SJohn Marino {
459*e4b17023SJohn Marino   if (protocol == NULL  ||  propertyName == NULL)
460*e4b17023SJohn Marino     return NULL;
461*e4b17023SJohn Marino 
462*e4b17023SJohn Marino   if (!requiredProperty  ||  !instanceProperty)
463*e4b17023SJohn Marino     return NULL;
464*e4b17023SJohn Marino 
465*e4b17023SJohn Marino   /* Check that it is a Protocol object before casting it to (struct
466*e4b17023SJohn Marino      objc_protocol *).  */
467*e4b17023SJohn Marino   if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
468*e4b17023SJohn Marino     return NULL;
469*e4b17023SJohn Marino 
470*e4b17023SJohn Marino   /* TODO: New ABI.  */
471*e4b17023SJohn Marino   /* The current ABI does not have any information on protocol properties.  */
472*e4b17023SJohn Marino   return NULL;
473*e4b17023SJohn Marino }
474*e4b17023SJohn Marino 
protocol_copyPropertyList(Protocol * protocol,unsigned int * numberOfReturnedProperties)475*e4b17023SJohn Marino Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties)
476*e4b17023SJohn Marino {
477*e4b17023SJohn Marino   unsigned int count = 0;
478*e4b17023SJohn Marino   Property *returnValue = NULL;
479*e4b17023SJohn Marino 
480*e4b17023SJohn Marino   /* Check that it is a Protocol object before casting it to (struct
481*e4b17023SJohn Marino      objc_protocol *).  */
482*e4b17023SJohn Marino   if (protocol == NULL  ||  protocol->class_pointer != objc_lookUpClass ("Protocol"))
483*e4b17023SJohn Marino     {
484*e4b17023SJohn Marino       if (numberOfReturnedProperties)
485*e4b17023SJohn Marino 	*numberOfReturnedProperties = 0;
486*e4b17023SJohn Marino 
487*e4b17023SJohn Marino       return NULL;
488*e4b17023SJohn Marino     }
489*e4b17023SJohn Marino 
490*e4b17023SJohn Marino   /* We do not acquire any lock because protocols are currently
491*e4b17023SJohn Marino      immutable.  We can freely iterate over a protocol structure.  */
492*e4b17023SJohn Marino 
493*e4b17023SJohn Marino   /* TODO: New ABI.  */
494*e4b17023SJohn Marino   /* The current ABI does not have any information on protocol properties.  */
495*e4b17023SJohn Marino   if (numberOfReturnedProperties)
496*e4b17023SJohn Marino     *numberOfReturnedProperties = count;
497*e4b17023SJohn Marino 
498*e4b17023SJohn Marino   return returnValue;
499*e4b17023SJohn Marino }
500*e4b17023SJohn Marino 
protocol_copyProtocolList(Protocol * protocol,unsigned int * numberOfReturnedProtocols)501*e4b17023SJohn Marino Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols)
502*e4b17023SJohn Marino {
503*e4b17023SJohn Marino   unsigned int count = 0;
504*e4b17023SJohn Marino   Protocol **returnValue = NULL;
505*e4b17023SJohn Marino   struct objc_protocol_list* proto_list;
506*e4b17023SJohn Marino 
507*e4b17023SJohn Marino   /* Check that it is a Protocol object before casting it to (struct
508*e4b17023SJohn Marino      objc_protocol *).  */
509*e4b17023SJohn Marino   if (protocol == NULL  ||  protocol->class_pointer != objc_lookUpClass ("Protocol"))
510*e4b17023SJohn Marino     {
511*e4b17023SJohn Marino       if (numberOfReturnedProtocols)
512*e4b17023SJohn Marino 	*numberOfReturnedProtocols = 0;
513*e4b17023SJohn Marino 
514*e4b17023SJohn Marino       return NULL;
515*e4b17023SJohn Marino     }
516*e4b17023SJohn Marino 
517*e4b17023SJohn Marino   /* We do not acquire any lock because protocols are currently
518*e4b17023SJohn Marino      immutable.  We can freely iterate over a protocol structure.  */
519*e4b17023SJohn Marino 
520*e4b17023SJohn Marino   /* Count how many protocols we have.  */
521*e4b17023SJohn Marino   proto_list = ((struct objc_protocol *)protocol)->protocol_list;
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino   while (proto_list)
524*e4b17023SJohn Marino     {
525*e4b17023SJohn Marino       count = count + proto_list->count;
526*e4b17023SJohn Marino       proto_list = proto_list->next;
527*e4b17023SJohn Marino     }
528*e4b17023SJohn Marino 
529*e4b17023SJohn Marino   if (count != 0)
530*e4b17023SJohn Marino     {
531*e4b17023SJohn Marino       unsigned int i = 0;
532*e4b17023SJohn Marino 
533*e4b17023SJohn Marino       /* Allocate enough memory to hold them.  */
534*e4b17023SJohn Marino       returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
535*e4b17023SJohn Marino 
536*e4b17023SJohn Marino       /* Copy the protocols.  */
537*e4b17023SJohn Marino       proto_list = ((struct objc_protocol *)protocol)->protocol_list;
538*e4b17023SJohn Marino 
539*e4b17023SJohn Marino       while (proto_list)
540*e4b17023SJohn Marino 	{
541*e4b17023SJohn Marino 	  size_t j;
542*e4b17023SJohn Marino 	  for (j = 0; j < proto_list->count; j++)
543*e4b17023SJohn Marino 	    {
544*e4b17023SJohn Marino 	      returnValue[i] = (Protocol *)proto_list->list[j];
545*e4b17023SJohn Marino 	      i++;
546*e4b17023SJohn Marino 	    }
547*e4b17023SJohn Marino 	  proto_list = proto_list->next;
548*e4b17023SJohn Marino 	}
549*e4b17023SJohn Marino 
550*e4b17023SJohn Marino       returnValue[i] = NULL;
551*e4b17023SJohn Marino     }
552*e4b17023SJohn Marino 
553*e4b17023SJohn Marino   if (numberOfReturnedProtocols)
554*e4b17023SJohn Marino     *numberOfReturnedProtocols = count;
555*e4b17023SJohn Marino 
556*e4b17023SJohn Marino   return returnValue;
557*e4b17023SJohn Marino }
558