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