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