]> git.saurik.com Git - apple/objc4.git/blob - runtime/Object.m
objc4-274.tar.gz
[apple/objc4.git] / runtime / Object.m
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 Object.m
27 Copyright 1988-1996 NeXT Software, Inc.
28 */
29
30 #import <objc/Object.h>
31 #import "objc-private.h"
32 #import <objc/objc-auto.h>
33 #import <objc/objc-runtime.h>
34 #import <objc/Protocol.h>
35 #import <stdarg.h>
36 #import <string.h>
37
38 OBJC_EXPORT id (*_cvtToId)(const char *);
39 OBJC_EXPORT id (*_poseAs)();
40
41
42 // Error Messages
43 static const char
44 _errNoMem[] = "failed -- out of memory(%s, %u)",
45 _errReAllocNil[] = "reallocating nil object",
46 _errReAllocFreed[] = "reallocating freed object",
47 _errReAllocTooSmall[] = "(%s, %u) requested size too small",
48 _errShouldHaveImp[] = "should have implemented the '%s' method.",
49 _errShouldNotImp[] = "should NOT have implemented the '%s' method.",
50 _errLeftUndone[] = "method '%s' not implemented",
51 _errBadSel[] = "method %s given invalid selector %s",
52 _errDoesntRecognize[] = "does not recognize selector %c%s";
53
54
55 @implementation Object
56
57
58 + initialize
59 {
60 return self;
61 }
62
63 - awake
64 {
65 return self;
66 }
67
68 + poseAs: aFactory
69 {
70 return (*_poseAs)(self, aFactory);
71 }
72
73 + new
74 {
75 id newObject = (*_alloc)((Class)self, 0);
76 struct objc_class * metaClass = ((struct objc_class *) self)->isa;
77 if (metaClass->version > 1)
78 return [newObject init];
79 else
80 return newObject;
81 }
82
83 + alloc
84 {
85 return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
86 }
87
88 + allocFromZone:(void *) z
89 {
90 return (*_zoneAlloc)((Class)self, 0, z);
91 }
92
93 - init
94 {
95 return self;
96 }
97
98 - (const char *)name
99 {
100 return ((struct objc_class *)isa)->name;
101 }
102
103 + (const char *)name
104 {
105 return ((struct objc_class *)self)->name;
106 }
107
108 - (unsigned)hash
109 {
110 return ((uarith_t)self) >> 2;
111 }
112
113 - (BOOL)isEqual:anObject
114 {
115 return anObject == self;
116 }
117
118 - free
119 {
120 return (*_dealloc)(self);
121 }
122
123 + free
124 {
125 return nil;
126 }
127
128 - self
129 {
130 return self;
131 }
132
133 - class
134 {
135 return (id)isa;
136 }
137
138 + class
139 {
140 return self;
141 }
142
143 - (void *)zone
144 {
145 void *z = malloc_zone_from_ptr(self);
146 return z ? z : malloc_default_zone();
147 }
148
149 + superclass
150 {
151 return ((struct objc_class *)self)->super_class;
152 }
153
154 - superclass
155 {
156 return ((struct objc_class *)isa)->super_class;
157 }
158
159 + (int) version
160 {
161 struct objc_class * class = (struct objc_class *) self;
162 return class->version;
163 }
164
165 + setVersion: (int) aVersion
166 {
167 struct objc_class * class = (struct objc_class *) self;
168 class->version = aVersion;
169 return self;
170 }
171
172 - (BOOL)isKindOf:aClass
173 {
174 register Class cls;
175 for (cls = isa; cls; cls = ((struct objc_class *)cls)->super_class)
176 if (cls == (Class)aClass)
177 return YES;
178 return NO;
179 }
180
181 - (BOOL)isMemberOf:aClass
182 {
183 return isa == (Class)aClass;
184 }
185
186 - (BOOL)isKindOfClassNamed:(const char *)aClassName
187 {
188 register Class cls;
189 for (cls = isa; cls; cls = ((struct objc_class *)cls)->super_class)
190 if (strcmp(aClassName, ((struct objc_class *)cls)->name) == 0)
191 return YES;
192 return NO;
193 }
194
195 - (BOOL)isMemberOfClassNamed:(const char *)aClassName
196 {
197 return strcmp(aClassName, ((struct objc_class *)isa)->name) == 0;
198 }
199
200 + (BOOL)instancesRespondTo:(SEL)aSelector
201 {
202 return class_respondsToMethod((Class)self, aSelector);
203 }
204
205 - (BOOL)respondsTo:(SEL)aSelector
206 {
207 return class_respondsToMethod(isa, aSelector);
208 }
209
210 - copy
211 {
212 return [self copyFromZone: [self zone]];
213 }
214
215 - copyFromZone:(void *)z
216 {
217 return (*_zoneCopy)(self, 0, z);
218 }
219
220 - (IMP)methodFor:(SEL)aSelector
221 {
222 return class_lookupMethod(isa, aSelector);
223 }
224
225 + (IMP)instanceMethodFor:(SEL)aSelector
226 {
227 return class_lookupMethod(self, aSelector);
228 }
229
230 #if defined(__alpha__)
231 #define MAX_RETSTRUCT_SIZE 256
232
233 typedef struct _foolGCC {
234 char c[MAX_RETSTRUCT_SIZE];
235 } _variableStruct;
236
237 typedef _variableStruct (*callReturnsStruct)();
238
239 OBJC_EXPORT long sizeOfReturnedStruct(char **);
240
241 long sizeOfType(char **pp)
242 {
243 char *p = *pp;
244 long stack_size = 0, n = 0;
245 switch(*p) {
246 case 'c':
247 case 'C':
248 stack_size += sizeof(char); // Alignment ?
249 break;
250 case 's':
251 case 'S':
252 stack_size += sizeof(short);// Alignment ?
253 break;
254 case 'i':
255 case 'I':
256 case '!':
257 stack_size += sizeof(int);
258 break;
259 case 'l':
260 case 'L':
261 stack_size += sizeof(long int);
262 break;
263 case 'f':
264 stack_size += sizeof(float);
265 break;
266 case 'd':
267 stack_size += sizeof(double);
268 break;
269 case '*':
270 case ':':
271 case '@':
272 case '%':
273 stack_size += sizeof(char*);
274 break;
275 case '{':
276 stack_size += sizeOfReturnedStruct(&p);
277 while(*p!='}') p++;
278 break;
279 case '[':
280 p++;
281 while(isdigit(*p))
282 n = 10 * n + (*p++ - '0');
283 stack_size += (n * sizeOfType(&p));
284 break;
285 default:
286 break;
287 }
288 *pp = p;
289 return stack_size;
290 }
291
292 long
293 sizeOfReturnedStruct(char **pp)
294 {
295 char *p = *pp;
296 long stack_size = 0, n = 0;
297 while(p!=NULL && *++p!='=') ; // skip the struct name
298 while(p!=NULL && *++p!='}')
299 stack_size += sizeOfType(&p);
300 return stack_size + 8; // Add 8 as a 'forfait value'
301 // to take alignment into account
302 }
303
304 - perform:(SEL)aSelector
305 {
306 char *p;
307 long stack_size;
308 _variableStruct *dummyRetVal;
309 Method method;
310
311 if (aSelector) {
312 method = class_getInstanceMethod((Class)self->isa,
313 aSelector);
314 if(method==NULL)
315 method = class_getClassMethod((Class)self->isa,
316 aSelector);
317 if(method!=NULL) {
318 p = &method->method_types[0];
319 if(*p=='{') {
320 // Method returns a structure
321 stack_size = sizeOfReturnedStruct(&p);
322 if(stack_size<MAX_RETSTRUCT_SIZE)
323 {
324 //
325 // The MAX_RETSTRUCT_SIZE value allow us to support methods that
326 // return structures whose size is not grater than
327 // MAX_RETSTRUCT_SIZE.
328 // This is because the compiler allocates space on the stack
329 // for the size of the return structure, and when the method
330 // returns, the structure is copied on the space allocated
331 // on the stack: if the structure is greater than the space
332 // allocated... bang! (the stack is gone:-)
333 //
334 ((callReturnsStruct)objc_msgSend)(self, aSelector);
335 }
336 else
337 {
338 dummyRetVal = (_variableStruct*) malloc(stack_size);
339
340 // Following asm code is equivalent to:
341 // *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector);
342 #if 0
343 asm("ldq $16,%0":"=g" (dummyRetVal):);
344 asm("ldq $17,%0":"=g" (self):);
345 asm("ldq $18,%0":"=g" (aSelector):);
346 asm("bis $31,1,$25");
347 asm("lda $27,objc_msgSend");
348 asm("jsr $26,($27),objc_msgSend");
349 asm("ldgp $29,0($26)");
350 #else
351 *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector);
352 #endif
353 free(dummyRetVal);
354 }
355 // When the method return a structure, we cannot return it here
356 // becuse we're not called in the right way, so we must return
357 // something else: wether it is self or NULL is a matter of taste.
358 return (id)NULL;
359 }
360 }
361 // We fall back here either because the method doesn't return
362 // a structure, or because method is NULL: in this latter
363 // case the call to msgSend will try to forward the message.
364 return objc_msgSend(self, aSelector);
365 }
366
367 // We fallback here only when aSelector is NULL
368 return [self error:_errBadSel, SELNAME(_cmd), aSelector];
369 }
370
371 - perform:(SEL)aSelector with:anObject
372 {
373 char *p;
374 long stack_size;
375 _variableStruct *dummyRetVal;
376 Method method;
377
378 if (aSelector) {
379 method = class_getInstanceMethod((Class)self->isa,
380 aSelector);
381 if(method==NULL)
382 method = class_getClassMethod((Class)self->isa,
383 aSelector);
384 if(method!=NULL) {
385 p = &method->method_types[0];
386 if(*p=='{') {
387 // Method returns a structure
388 stack_size = sizeOfReturnedStruct(&p);
389 if(stack_size<MAX_RETSTRUCT_SIZE)
390 {
391 //
392 // The MAX_RETSTRUCT_SIZE value allow us to support methods that
393 // return structures whose size is not grater than
394 // MAX_RETSTRUCT_SIZE.
395 // This is because the compiler allocates space on the stack
396 // for the size of the return structure, and when the method
397 // returns, the structure is copied on the space allocated
398 // on the stack: if the structure is greater than the space
399 // allocated... bang! (the stack is gone:-)
400 //
401 ((callReturnsStruct)objc_msgSend)(self, aSelector, anObject);
402 }
403 else
404 {
405 dummyRetVal = (_variableStruct*) malloc(stack_size);
406
407 // Following asm code is equivalent to:
408 // *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector,anObject);
409 #if 0
410 asm("ldq $16,%0":"=g" (dummyRetVal):);
411 asm("ldq $17,%0":"=g" (self):);
412 asm("ldq $18,%0":"=g" (aSelector):);
413 asm("ldq $19,%0":"=g" (anObject):);
414 asm("bis $31,1,$25");
415 asm("lda $27,objc_msgSend");
416 asm("jsr $26,($27),objc_msgSend");
417 asm("ldgp $29,0($26)");
418 #else
419 *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector,anObject);
420 #endif
421 free(dummyRetVal);
422 }
423 // When the method return a structure, we cannot return it here
424 // becuse we're not called in the right way, so we must return
425 // something else: wether it is self or NULL is a matter of taste.
426 return (id)NULL;
427 }
428 }
429 // We fall back here either because the method doesn't return
430 // a structure, or because method is NULL: in this latter
431 // case the call to msgSend will try to forward the message.
432 return objc_msgSend(self, aSelector, anObject);
433 }
434
435 // We fallback here only when aSelector is NULL
436 return [self error:_errBadSel, SELNAME(_cmd), aSelector];
437 }
438
439 - perform:(SEL)aSelector with:obj1 with:obj2
440 {
441 char *p;
442 long stack_size;
443 _variableStruct *dummyRetVal;
444 Method method;
445
446 if (aSelector) {
447 method = class_getInstanceMethod((Class)self->isa,
448 aSelector);
449 if(method==NULL)
450 method = class_getClassMethod((Class)self->isa,
451 aSelector);
452 if(method!=NULL) {
453 p = &method->method_types[0];
454 if(*p=='{') {
455 // Method returns a structure
456 stack_size = sizeOfReturnedStruct(&p);
457 if(stack_size<MAX_RETSTRUCT_SIZE)
458 {
459 //
460 // The MAX_RETSTRUCT_SIZE value allow us to support methods that
461 // return structures whose size is not grater than
462 // MAX_RETSTRUCT_SIZE.
463 // This is because the compiler allocates space on the stack
464 // for the size of the return structure, and when the method
465 // returns, the structure is copied on the space allocated
466 // on the stack: if the structure is greater than the space
467 // allocated... bang! (the stack is gone:-)
468 //
469 ((callReturnsStruct)objc_msgSend)(self, aSelector, obj1, obj2);
470 }
471 else
472 {
473 dummyRetVal = (_variableStruct*) malloc(stack_size);
474
475 // Following asm code is equivalent to:
476 // *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector,obj1,obj2);
477
478 #if 0
479 asm("ldq $16,%0":"=g" (dummyRetVal):);
480 asm("ldq $17,%0":"=g" (self):);
481 asm("ldq $18,%0":"=g" (aSelector):);
482 asm("ldq $19,%0":"=g" (obj1):);
483 asm("ldq $20,%0":"=g" (obj2):);
484 asm("bis $31,1,$25");
485 asm("lda $27,objc_msgSend");
486 asm("jsr $26,($27),objc_msgSend");
487 asm("ldgp $29,0($26)");
488 #else
489 *dummyRetVal=((callReturnsStruct)objc_msgSend)(self,aSelector,obj1,obj2);
490 #endif
491 free(dummyRetVal);
492 }
493 // When the method return a structure, we cannot return it here
494 // becuse we're not called in the right way, so we must return
495 // something else: wether it is self or NULL is a matter of taste.
496 return (id)NULL;
497 }
498 }
499 // We fall back here either because the method doesn't return
500 // a structure, or because method is NULL: in this latter
501 // case the call to msgSend will try to forward the message.
502 return objc_msgSend(self, aSelector, obj1, obj2);
503 }
504
505 // We fallback here only when aSelector is NULL
506 return [self error:_errBadSel, SELNAME(_cmd), aSelector];
507
508 }
509 #else
510 - perform:(SEL)aSelector
511 {
512 if (aSelector)
513 return objc_msgSend(self, aSelector);
514 else
515 return [self error:_errBadSel, SELNAME(_cmd), aSelector];
516 }
517
518 - perform:(SEL)aSelector with:anObject
519 {
520 if (aSelector)
521 return objc_msgSend(self, aSelector, anObject);
522 else
523 return [self error:_errBadSel, SELNAME(_cmd), aSelector];
524 }
525
526 - perform:(SEL)aSelector with:obj1 with:obj2
527 {
528 if (aSelector)
529 return objc_msgSend(self, aSelector, obj1, obj2);
530 else
531 return [self error:_errBadSel, SELNAME(_cmd), aSelector];
532 }
533 #endif
534
535 - subclassResponsibility:(SEL)aSelector
536 {
537 return [self error:_errShouldHaveImp, sel_getName(aSelector)];
538 }
539
540 - notImplemented:(SEL)aSelector
541 {
542 return [self error:_errLeftUndone, sel_getName(aSelector)];
543 }
544
545 - doesNotRecognize:(SEL)aMessage
546 {
547 return [self error:_errDoesntRecognize,
548 ISMETA (isa) ? '+' : '-', SELNAME(aMessage)];
549 }
550
551 - error:(const char *)aCStr, ...
552 {
553 va_list ap;
554 va_start(ap,aCStr);
555 (*_error)(self, aCStr, ap);
556 _objc_error (self, aCStr, ap); /* In case (*_error)() returns. */
557 va_end(ap);
558 return nil;
559 }
560
561 - (void) printForDebugger:(void *)stream
562 {
563 }
564
565 - write:(void *) stream
566 {
567 return self;
568 }
569
570 - read:(void *) stream
571 {
572 return self;
573 }
574
575 - forward: (SEL) sel : (marg_list) args
576 {
577 return [self doesNotRecognize: sel];
578 }
579
580 /* this method is not part of the published API */
581
582 - (unsigned)methodArgSize:(SEL)sel
583 {
584 Method method = class_getInstanceMethod((Class)isa, sel);
585 if (! method) return 0;
586 return method_getSizeOfArguments(method);
587 }
588
589 #if defined(__alpha__)
590
591 typedef struct {
592 unsigned long int i16;
593 unsigned long int i17;
594 unsigned long int i18;
595 unsigned long int i19;
596 unsigned long int i20;
597 unsigned long int i21;
598 unsigned long int i25;
599 unsigned long int f16;
600 unsigned long int f17;
601 unsigned long int f18;
602 unsigned long int f19;
603 unsigned long int f20;
604 unsigned long int f21;
605 unsigned long int sp;
606 } *_m_args_p;
607
608 - performv: (SEL) sel : (marg_list) args
609 {
610 char * p;
611 long stack_size;
612 Method method;
613 unsigned long int size;
614 char scratchMem[MAX_RETSTRUCT_SIZE];
615 char * scratchMemP;
616
617 // Messages to nil object always return nil
618 if (! self) return nil;
619
620 // Got to have a selector
621 if (!sel)
622 return [self error:_errBadSel, SELNAME(_cmd), sel];
623
624 // Handle a method which returns a structure and
625 // has been called as such
626 if (((_m_args_p)args)->i25){
627 // Calculate size of the marg_list from the method's
628 // signature. This looks for the method in self
629 // and its superclasses.
630 size = [self methodArgSize: sel];
631
632 // If neither self nor its superclasses implement
633 // the method, forward the message because self
634 // might know someone who does. This is a
635 // "chained" forward...
636 if (! size) return [self forward: sel: args];
637
638 // Message self with the specified selector and arguments
639 return objc_msgSendv (self, sel, size, args);
640 }
641
642 // Look for instance method in self's class and superclasses
643 method = class_getInstanceMethod((Class)self->isa,sel);
644
645 // Look for class method in self's class and superclass
646 if(method==NULL)
647 method = class_getClassMethod((Class)self->isa,sel);
648
649 // If neither self nor its superclasses implement
650 // the method, forward the message because self
651 // might know someone who does. This is a
652 // "chained" forward...
653 if(method==NULL)
654 return [self forward: sel: args];
655
656 // Calculate size of the marg_list from the method's
657 // signature.
658 size = method_getSizeOfArguments(method);
659
660 // Ready to send message now if the return type
661 // is not a structure
662 p = &method->method_types[0];
663 if(*p!='{')
664 return objc_msgSendv(self, sel, size, args);
665
666 // Method returns a structure
667 stack_size = sizeOfReturnedStruct(&p);
668 if(stack_size>=MAX_RETSTRUCT_SIZE)
669 scratchMemP = (char*)malloc(stack_size);
670 else
671 scratchMemP = &scratchMem[0];
672
673 // Set i25 so objc_msgSendv will know that method returns a structure
674 ((_m_args_p)args)->i25 = 1;
675
676 // Set first param of method to be called to safe return address
677 ((_m_args_p)args)->i16 = (unsigned long int) scratchMemP;
678 objc_msgSendv(self, sel, size, args);
679
680 if(stack_size>=MAX_RETSTRUCT_SIZE)
681 free(scratchMemP);
682
683 return (id)NULL;
684 }
685 #else
686 - performv: (SEL) sel : (marg_list) args
687 {
688 unsigned size;
689 #if hppa && 0
690 void *ret;
691
692 // Save ret0 so methods that return a struct might work.
693 asm("copy %%r28, %0": "=r"(ret): );
694 #endif hppa
695
696 // Messages to nil object always return nil
697 if (! self) return nil;
698
699 // Calculate size of the marg_list from the method's
700 // signature. This looks for the method in self
701 // and its superclasses.
702 size = [self methodArgSize: sel];
703
704 // If neither self nor its superclasses implement
705 // it, forward the message because self might know
706 // someone who does. This is a "chained" forward...
707 if (! size) return [self forward: sel: args];
708
709 #if hppa && 0
710 // Unfortunately, it looks like the compiler puts something else in
711 // r28 right after this instruction, so this is all for naught.
712 asm("copy %0, %%r28": : "r"(ret));
713 #endif hppa
714
715 // Message self with the specified selector and arguments
716 return objc_msgSendv (self, sel, size, args);
717 }
718 #endif
719
720 /* Testing protocol conformance */
721
722 - (BOOL) conformsTo: (Protocol *)aProtocolObj
723 {
724 return [(id)isa conformsTo:aProtocolObj];
725 }
726
727 + (BOOL) conformsTo: (Protocol *)aProtocolObj
728 {
729 struct objc_class * class;
730
731 for (class = self; class; class = class->super_class)
732 {
733 if (class->isa->version >= 3)
734 {
735 struct objc_protocol_list *protocols = class->protocols;
736
737 while (protocols)
738 {
739 int i;
740
741 for (i = 0; i < protocols->count; i++)
742 {
743 Protocol *p = protocols->list[i];
744
745 if ([p conformsTo:aProtocolObj])
746 return YES;
747 }
748
749 if (class->isa->version <= 4)
750 break;
751
752 protocols = protocols->next;
753 }
754 }
755 }
756 return NO;
757 }
758
759
760 /* Looking up information for a method */
761
762 - (struct objc_method_description *) descriptionForMethod:(SEL)aSelector
763 {
764 struct objc_class * cls;
765 struct objc_method_description *m;
766
767 /* Look in the protocols first. */
768 for (cls = isa; cls; cls = cls->super_class)
769 {
770 if (cls->isa->version >= 3)
771 {
772 struct objc_protocol_list *protocols = cls->protocols;
773
774 while (protocols)
775 {
776 int i;
777
778 for (i = 0; i < protocols->count; i++)
779 {
780 Protocol *p = protocols->list[i];
781
782 if (ISMETA (cls))
783 m = [p descriptionForClassMethod:aSelector];
784 else
785 m = [p descriptionForInstanceMethod:aSelector];
786
787 if (m) {
788 return m;
789 }
790 }
791
792 if (cls->isa->version <= 4)
793 break;
794
795 protocols = protocols->next;
796 }
797 }
798 }
799
800 /* Then try the class implementations. */
801 for (cls = isa; cls; cls = cls->super_class) {
802 void *iterator = 0;
803 int i;
804 struct objc_method_list *mlist;
805 while ( (mlist = class_nextMethodList( cls, &iterator )) ) {
806 for (i = 0; i < mlist->method_count; i++)
807 if (mlist->method_list[i].method_name == aSelector) {
808 struct objc_method_description *m;
809 m = (struct objc_method_description *)&mlist->method_list[i];
810 return m;
811 }
812 }
813 }
814
815 return 0;
816 }
817
818 + (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSelector
819 {
820 struct objc_class * cls;
821
822 /* Look in the protocols first. */
823 for (cls = self; cls; cls = cls->super_class)
824 {
825 if (cls->isa->version >= 3)
826 {
827 struct objc_protocol_list *protocols = cls->protocols;
828
829 while (protocols)
830 {
831 int i;
832
833 for (i = 0; i < protocols->count; i++)
834 {
835 Protocol *p = protocols->list[i];
836 struct objc_method_description *m;
837
838 if ((m = [p descriptionForInstanceMethod:aSelector]))
839 return m;
840 }
841
842 if (cls->isa->version <= 4)
843 break;
844
845 protocols = protocols->next;
846 }
847 }
848 }
849
850 /* Then try the class implementations. */
851 for (cls = self; cls; cls = cls->super_class) {
852 void *iterator = 0;
853 int i;
854 struct objc_method_list *mlist;
855 while ( (mlist = class_nextMethodList( cls, &iterator )) ) {
856 for (i = 0; i < mlist->method_count; i++)
857 if (mlist->method_list[i].method_name == aSelector) {
858 struct objc_method_description *m;
859 m = (struct objc_method_description *)&mlist->method_list[i];
860 return m;
861 }
862 }
863 }
864
865 return 0;
866 }
867
868
869 /* Obsolete methods (for binary compatibility only). */
870
871 + superClass
872 {
873 return [self superclass];
874 }
875
876 - superClass
877 {
878 return [self superclass];
879 }
880
881 - (BOOL)isKindOfGivenName:(const char *)aClassName
882 {
883 return [self isKindOfClassNamed: aClassName];
884 }
885
886 - (BOOL)isMemberOfGivenName:(const char *)aClassName
887 {
888 return [self isMemberOfClassNamed: aClassName];
889 }
890
891 - (struct objc_method_description *) methodDescFor:(SEL)aSelector
892 {
893 return [self descriptionForMethod: aSelector];
894 }
895
896 + (struct objc_method_description *) instanceMethodDescFor:(SEL)aSelector
897 {
898 return [self descriptionForInstanceMethod: aSelector];
899 }
900
901 - findClass:(const char *)aClassName
902 {
903 return (*_cvtToId)(aClassName);
904 }
905
906 - shouldNotImplement:(SEL)aSelector
907 {
908 return [self error:_errShouldNotImp, sel_getName(aSelector)];
909 }
910
911 @end
912
913 static id _internal_object_copyFromZone(Object *anObject, unsigned nBytes, void *z)
914 {
915 id obj;
916 register unsigned siz;
917
918 if (anObject == nil)
919 return nil;
920
921 obj = (*_zoneAlloc)(anObject->isa, nBytes, z);
922 siz = ((struct objc_class *)anObject->isa)->instance_size + nBytes;
923 bcopy((const char*)anObject, (char*)obj, siz);
924 return obj;
925 }
926
927 static id _internal_object_copy(Object *anObject, unsigned nBytes)
928 {
929 void *z= malloc_zone_from_ptr(anObject);
930 return _internal_object_copyFromZone(anObject,
931 nBytes,
932 z ? z : malloc_default_zone());
933 }
934
935 static id _internal_object_dispose(Object *anObject)
936 {
937 if (anObject==nil) return nil;
938 object_cxxDestruct((id)anObject);
939 anObject->isa = _objc_getFreedObjectClass ();
940 free(anObject);
941 return nil;
942 }
943
944 static id _internal_object_reallocFromZone(Object *anObject, unsigned nBytes, void *z)
945 {
946 Object *newObject;
947 struct objc_class * tmp;
948
949 if (anObject == nil)
950 __objc_error(nil, _errReAllocNil, 0);
951
952 if (anObject->isa == _objc_getFreedObjectClass ())
953 __objc_error(anObject, _errReAllocFreed, 0);
954
955 if (nBytes < ((struct objc_class *)anObject->isa)->instance_size)
956 __objc_error(anObject, _errReAllocTooSmall,
957 object_getClassName(anObject), nBytes);
958
959 // Make sure not to modify space that has been declared free
960 tmp = anObject->isa;
961 anObject->isa = _objc_getFreedObjectClass ();
962 newObject = (Object*)malloc_zone_realloc(z, (void*)anObject, (size_t)nBytes);
963 if (newObject) {
964 newObject->isa = tmp;
965 return newObject;
966 }
967 else
968 {
969 __objc_error(anObject, _errNoMem,
970 object_getClassName(anObject), nBytes);
971 return nil;
972 }
973 }
974
975 static id _internal_object_realloc(Object *anObject, unsigned nBytes)
976 {
977 void *z= malloc_zone_from_ptr(anObject);
978 return _internal_object_reallocFromZone(anObject,
979 nBytes,
980 z ? z : malloc_default_zone());
981 }
982
983 /* Functional Interface to system primitives */
984
985 id object_copy(Object *anObject, unsigned nBytes)
986 {
987 return (*_copy)(anObject, nBytes);
988 }
989
990 id object_copyFromZone(Object *anObject, unsigned nBytes, void *z)
991 {
992 return (*_zoneCopy)(anObject, nBytes, z);
993 }
994
995 id object_dispose(Object *anObject)
996 {
997 return (*_dealloc)(anObject);
998 }
999
1000 id object_realloc(Object *anObject, unsigned nBytes)
1001 {
1002 return (*_realloc)(anObject, nBytes);
1003 }
1004
1005 id object_reallocFromZone(Object *anObject, unsigned nBytes, void *z)
1006 {
1007 return (*_zoneRealloc)(anObject, nBytes, z);
1008 }
1009
1010 Ivar object_setInstanceVariable(id obj, const char *name, void *value)
1011 {
1012 Ivar ivar = 0;
1013
1014 if (obj && name) {
1015 if ((ivar = class_getInstanceVariable(((Object*)obj)->isa, name))) {
1016 objc_assign_ivar((id)value, obj, ivar->ivar_offset);
1017 }
1018 }
1019 return ivar;
1020 }
1021
1022 Ivar object_getInstanceVariable(id obj, const char *name, void **value)
1023 {
1024 Ivar ivar = 0;
1025
1026 if (obj && name) {
1027 void **ivaridx;
1028
1029 if ((ivar = class_getInstanceVariable(((Object*)obj)->isa, name))) {
1030 ivaridx = (void **)((char *)obj + ivar->ivar_offset);
1031 *value = *ivaridx;
1032 } else
1033 *value = 0;
1034 }
1035 return ivar;
1036 }
1037
1038
1039 id (*_copy)(id, unsigned) = _internal_object_copy;
1040 id (*_realloc)(id, unsigned) = _internal_object_realloc;
1041 id (*_dealloc)(id) = _internal_object_dispose;
1042 id (*_cvtToId)(const char *) = objc_lookUpClass;
1043 SEL (*_cvtToSel)(const char *) = sel_getUid;
1044 void (*_error)() = (void(*)())_objc_error;
1045 id (*_zoneCopy)(id, unsigned, void *) = _internal_object_copyFromZone;
1046 id (*_zoneRealloc)(id, unsigned, void *) = _internal_object_reallocFromZone;