OSDN Git Service

(-compare:, -shouldNotImplement:): Added.
[pf3gnuchains/gcc-fork.git] / gcc / objc / Object.m
1 /* The implementation of class Object for Objective-C.
2    Copyright (C) 1993 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 GNU CC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /* As a special exception, if you link this library with files compiled
21    with GCC to produce an executable, this does not cause the resulting
22    executable to be covered by the GNU General Public License.  This
23    exception does not however invalidate any other reasons why the
24    executable file might be covered by the GNU General Public License. */
25
26 #include "objc/Object.h"
27 #include "objc/Protocol.h"
28 #include "objc/objc-api.h"
29
30 #include "gstdarg.h"
31 extern void (*_objc_error)(id object, const char *format, va_list);
32
33 extern int errno;
34
35 #define MAX_CLASS_NAME_LEN 256
36
37 @implementation Object
38
39 + initialize
40 {
41   return self;
42 }
43
44 - init
45 {
46   return self;
47 }
48
49 + new
50 {
51   return [[self alloc] init];
52 }
53
54 + alloc
55 {
56   return class_create_instance(self);
57 }
58
59 - free
60 {
61   return object_dispose(self);
62 }
63
64 - copy
65 {
66   return [[self shallowCopy] deepen];
67 }
68
69 - shallowCopy
70 {
71   return object_copy(self);
72 }
73
74 - deepen
75 {
76   return self;
77 }
78
79 - deepCopy
80 {
81   return [self copy];
82 }
83
84 - (Class*)class
85 {
86   return object_get_class(self);
87 }
88
89 - (Class*)superClass
90 {
91   return object_get_super_class(self);
92 }
93
94 - (MetaClass*)metaClass
95 {
96   return object_get_meta_class(self);
97 }
98
99 - (const char *)name
100 {
101   return object_get_class_name(self);
102 }
103
104 - self
105 {
106   return self;
107 }
108
109 - (unsigned int)hash
110 {
111   return (size_t)self;
112 }
113
114 - (BOOL)isEqual:anObject
115 {
116   return self==anObject;
117 }
118
119 - (int)compare:anotherObject;
120 {
121   if ([self isEqual:anotherObject])
122     return 0;
123   // Ordering objects by their address is pretty useless, 
124   // so subclasses should override this is some useful way.
125   else if (self > anotherObject)
126     return 1;
127   else 
128     return -1;
129 }
130
131 - (BOOL)isMetaClass
132 {
133   return NO;
134 }
135
136 - (BOOL)isClass
137 {
138   return object_is_class(self);
139 }
140
141 - (BOOL)isInstance
142 {
143   return object_is_instance(self);
144 }
145
146 - (BOOL)isKindOf:(Class*)aClassObject
147 {
148   Class* class;
149
150   for (class = self->isa; class!=Nil; class = class_get_super_class(class))
151     if (class==aClassObject)
152       return YES;
153   return NO;
154 }
155
156 - (BOOL)isMemberOf:(Class*)aClassObject
157 {
158   return self->isa==aClassObject;
159 }
160
161 - (BOOL)isKindOfClassNamed:(const char *)aClassName
162 {
163   Class* class;
164
165   if (aClassName!=NULL)
166     for (class = self->isa; class!=Nil; class = class_get_super_class(class))
167       if (!strcmp(class_get_class_name(class), aClassName))
168         return YES;
169   return NO;
170 }
171
172 - (BOOL)isMemberOfClassNamed:(const char *)aClassName
173 {
174   return ((aClassName!=NULL)
175           &&!strcmp(class_get_class_name(self->isa), aClassName));
176 }
177
178 + (BOOL)instancesRespondTo:(SEL)aSel
179 {
180   return class_get_instance_method(self, aSel)!=METHOD_NULL;
181 }
182
183 - (BOOL)respondsTo:(SEL)aSel
184 {
185   return ((object_is_instance(self)
186            ?class_get_instance_method(self->isa, aSel)
187            :class_get_class_method(self->isa, aSel))!=METHOD_NULL);
188 }
189
190 + (IMP)instanceMethodFor:(SEL)aSel
191 {
192   return method_get_imp(class_get_instance_method(self, aSel));
193 }
194
195 // Indicates if the receiving class or instance conforms to the given protocol
196 // not usually overridden by subclasses
197 - (BOOL) conformsTo: (Protocol*)aProtocol
198 {
199   int i;
200   struct objc_protocol_list* proto_list;
201
202   for (proto_list = isa->protocols;
203        proto_list; proto_list = proto_list->next)
204     {
205       for (i=0; i < proto_list->count; i++)
206       {
207         if ([proto_list->list[i] conformsTo: aProtocol])
208           return YES;
209       }
210     }
211
212   if ([self superClass])
213     return [[self superClass] conformsTo: aProtocol];
214   else
215     return NO;
216 }
217
218 - (IMP)methodFor:(SEL)aSel
219 {
220   return (method_get_imp(object_is_instance(self)
221                          ?class_get_instance_method(self->isa, aSel)
222                          :class_get_class_method(self->isa, aSel)));
223 }
224
225 + (struct objc_method_description *)descriptionForInstanceMethod:(SEL)aSel
226 {
227   return ((struct objc_method_description *)
228            class_get_instance_method(self, aSel));
229 }
230
231 - (struct objc_method_description *)descriptionForMethod:(SEL)aSel
232 {
233   return ((struct objc_method_description *)
234            (object_is_instance(self)
235             ?class_get_instance_method(self->isa, aSel)
236             :class_get_class_method(self->isa, aSel)));
237 }
238
239 - perform:(SEL)aSel
240 {
241   IMP msg = objc_msg_lookup(self, aSel);
242   if (!msg)
243     return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
244   return (*msg)(self, aSel);
245 }
246
247 - perform:(SEL)aSel with:anObject
248 {
249   IMP msg = objc_msg_lookup(self, aSel);
250   if (!msg)
251     return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
252   return (*msg)(self, aSel, anObject);
253 }
254
255 - perform:(SEL)aSel with:anObject1 with:anObject2
256 {
257   IMP msg = objc_msg_lookup(self, aSel);
258   if (!msg)
259     return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
260   return (*msg)(self, aSel, anObject1, anObject2);
261 }
262
263 - forward:(SEL)aSel :(arglist_t)argFrame
264 {
265   return [self doesNotRecognize: aSel];
266 }
267
268 - performv:(SEL)aSel :(arglist_t)argFrame
269 {
270   return objc_msg_sendv(self, aSel, argFrame);
271 }
272
273 + poseAs:(Class*)aClassObject
274 {
275   return class_pose_as(self, aClassObject);
276 }
277
278 - (Class*)transmuteClassTo:(Class*)aClassObject
279 {
280   if (object_is_instance(self))
281     if (class_is_class(aClassObject))
282       if (class_get_instance_size(aClassObject)==class_get_instance_size(isa))
283         if ([self isKindOf:aClassObject])
284           {
285             Class* old_isa = isa;
286             isa = aClassObject;
287             return old_isa;
288           }
289   return nil;
290 }
291
292 - subclassResponsibility:(SEL)aSel
293 {
294   return [self error:"subclass should override %s", sel_get_name(aSel)];
295 }
296
297 - notImplemented:(SEL)aSel
298 {
299   return [self error:"method %s not implemented", sel_get_name(aSel)];
300 }
301
302 - shouldNotImplement:(SEL)aSel
303 {
304   return [self error:"%s should not implement %s", 
305                      object_get_class_name(self), sel_get_name(aSel)];
306 }
307
308 - doesNotRecognize:(SEL)aSel
309 {
310   return [self error:"%s does not recognize %s",
311                      object_get_class_name(self), sel_get_name(aSel)];
312 }
313
314 - error:(const char *)aString, ...
315 {
316 #define FMT "error: %s (%s)\n%s\n"
317   char fmt[(strlen((char*)FMT)+strlen((char*)object_get_class_name(self))
318             +((aString!=NULL)?strlen((char*)aString):0)+8)];
319   va_list ap;
320
321   sprintf(fmt, FMT, object_get_class_name(self),
322                     object_is_instance(self)?"instance":"class",
323                     (aString!=NULL)?aString:"");
324   va_start(ap, aString);
325   (*_objc_error)(self, fmt, ap);
326   va_end(ap);
327   return nil;
328 #undef FMT
329 }
330
331 + (int)version
332 {
333   return class_get_version(self);
334 }
335
336 + setVersion:(int)aVersion
337 {
338   class_set_version(self, aVersion);
339   return self;
340 }
341
342 + (int)streamVersion: (TypedStream*)aStream
343 {
344 #ifndef __alpha__
345   if (aStream->mode == OBJC_READONLY)
346     return objc_get_stream_class_version (aStream, self);
347   else
348 #endif
349     return class_get_version (self);
350 }
351
352 // These are used to write or read the instance variables 
353 // declared in this particular part of the object.  Subclasses
354 // should extend these, by calling [super read/write: aStream]
355 // before doing their own archiving.  These methods are private, in
356 // the sense that they should only be called from subclasses.
357
358 - read: (TypedStream*)aStream
359 {
360   // [super read: aStream];  
361   return self;
362 }
363
364 - write: (TypedStream*)aStream
365 {
366   // [super write: aStream];
367   return self;
368 }
369
370 - awake
371 {
372   // [super awake];
373   return self;
374 }
375
376 @end