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