OSDN Git Service

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