|
|
1.1 root 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.0 (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, 1989 NeXT, Inc.
27: */
28:
29: #ifdef SHLIB
30: #import "shlib.h"
31: #endif SHLIB
32:
33: #import "objc-private.h"
34: #import <stdarg.h>
35: #import <string.h>
36:
37: #import "objc-runtime.h"
38: #import "typedstream.h"
39: #import "Protocol.h"
40:
41: extern id (*_cvtToId)(const char *);
42: extern id (*_poseAs)();
43:
44: #define ISMETA(cls) ((cls)->info & CLS_META)
45:
46: // Error Messages
47: static const char
48: _errNoMem[] = "failed -- out of memory(%s, %u)",
49: _errReAllocNil[] = "reallocating nil object",
50: _errReAllocFreed[] = "reallocating freed object",
51: _errReAllocTooSmall[] = "(%s, %u) requested size too small",
52: _errShouldHaveImp[] = "should have implemented the '%s' method.",
53: _errShouldNotImp[] = "should NOT have implemented the '%s' method.",
54: _errLeftUndone[] = "method '%s' not implemented",
55: _errBadSel[] = "method %s given invalid selector %s",
56: _errDoesntRecognize[] = "does not recognize selector %c%s";
57:
58: #import "Object.h"
59:
60: @implementation Object
61:
62:
63: + initialize
64: {
65: return self;
66: }
67:
68: - awake
69: {
70: return self;
71: }
72:
73: + poseAs: aFactory
74: {
75: return (*_poseAs)(self, aFactory);
76: }
77:
78: + new
79: {
80: id newObject = (*_alloc)((Class)self, 0);
81: Class metaClass = ((Class) self)->isa;
82: if (metaClass->version > 1)
83: return [newObject init];
84: else
85: return newObject;
86: }
87:
88: + alloc
89: {
90: return (*_zoneAlloc)((Class)self, 0, NXDefaultMallocZone());
91: }
92:
93: + allocFromZone:(NXZone *) zone
94: {
95: return (*_zoneAlloc)((Class)self, 0, zone);
96: }
97:
98: - init
99: {
100: return self;
101: }
102:
103: - (const char *)name
104: {
105: return isa->name;
106: }
107:
108: + (const char *)name
109: {
110: return ((Class)self)->name;
111: }
112:
113: - (unsigned)hash
114: {
115: return ((unsigned)self) >> 2;
116: }
117:
118: - (BOOL)isEqual:anObject
119: {
120: return anObject == self;
121: }
122:
123: - free
124: {
125: return (*_dealloc)(self);
126: }
127:
128: + free
129: {
130: return nil;
131: }
132:
133: - self
134: {
135: return self;
136: }
137:
138: - class
139: {
140: return (id)isa;
141: }
142:
143: + class
144: {
145: return self;
146: }
147:
148: - (NXZone *)zone
149: {
150: NXZone *zone = NXZoneFromPtr(self);
151: return zone ? zone : NXDefaultMallocZone();
152: }
153:
154: + superclass
155: {
156: return ((Class)self)->super_class;
157: }
158:
159: - superclass
160: {
161: return isa->super_class;
162: }
163:
164: + (int) version
165: {
166: Class class = (Class) self;
167: return class->version;
168: }
169:
170: + setVersion: (int) aVersion
171: {
172: Class class = (Class) self;
173: class->version = aVersion;
174: return self;
175: }
176:
177: - (BOOL)isKindOf:aClass
178: {
179: register Class cls;
180: for (cls = isa; cls; cls = cls->super_class)
181: if (cls == (Class)aClass)
182: return YES;
183: return NO;
184: }
185:
186: - (BOOL)isMemberOf:aClass
187: {
188: return isa == (Class)aClass;
189: }
190:
191: - (BOOL)isKindOfClassNamed:(const char *)aClassName
192: {
193: register Class cls;
194: for (cls = isa; cls; cls = cls->super_class)
195: if (strcmp(aClassName, cls->name) == 0)
196: return YES;
197: return NO;
198: }
199:
200: - (BOOL)isMemberOfClassNamed:(const char *)aClassName
201: {
202: return strcmp(aClassName, isa->name) == 0;
203: }
204:
205: + (BOOL)instancesRespondTo:(SEL)aSelector
206: {
207: return class_respondsToMethod((Class)self, aSelector);
208: }
209:
210: - (BOOL)respondsTo:(SEL)aSelector
211: {
212: return class_respondsToMethod(isa, aSelector);
213: }
214:
215: - copy
216: {
217: return [self copyFromZone: [self zone]];
218: }
219:
220: - copyFromZone:(NXZone *)zone
221: {
222: return (*_zoneCopy)(self, 0, zone);
223: }
224:
225: - (IMP)methodFor:(SEL)aSelector
226: {
227: return class_lookupMethod(isa, aSelector);
228: }
229:
230: + (IMP)instanceMethodFor:(SEL)aSelector
231: {
232: return class_lookupMethod(self, aSelector);
233: }
234:
235: - perform:(SEL)aSelector
236: {
237: if (aSelector)
238: return objc_msgSend(self, aSelector);
239: else
240: return [self error:_errBadSel, SELNAME(_cmd), aSelector];
241: }
242:
243: - perform:(SEL)aSelector with:anObject
244: {
245: if (aSelector)
246: return objc_msgSend(self, aSelector, anObject);
247: else
248: return [self error:_errBadSel, SELNAME(_cmd), aSelector];
249: }
250:
251: - perform:(SEL)aSelector with:obj1 with:obj2
252: {
253: if (aSelector)
254: return objc_msgSend(self, aSelector, obj1, obj2);
255: else
256: return [self error:_errBadSel, SELNAME(_cmd), aSelector];
257: }
258:
259: - subclassResponsibility:(SEL)aSelector
260: {
261: return [self error:_errShouldHaveImp, sel_getName(aSelector)];
262: }
263:
264: - notImplemented:(SEL)aSelector
265: {
266: return [self error:_errLeftUndone, sel_getName(aSelector)];
267: }
268:
269: - doesNotRecognize:(SEL)aMessage
270: {
271: return [self error:_errDoesntRecognize,
272: ISMETA (isa) ? '+' : '-', SELNAME(aMessage)];
273: }
274:
275: - error:(const char *)aCStr, ...
276: {
277: va_list ap;
278: va_start(ap,aCStr);
279: (*_error)(self, aCStr, ap);
280: _objc_error (self, aCStr, ap); /* In case (*_error)() returns. */
281: va_end(ap);
282: return nil;
283: }
284:
285: - (void) printForDebugger:(NXStream *)stream
286: {
287: NXPrintf (stream, "<%s: 0x%x>", object_getClassName (self), self);
288: NXFlush (stream);
289: }
290:
291: - write:(NXTypedStream *) stream
292: {
293: return self;
294: }
295:
296: - read:(NXTypedStream *) stream
297: {
298: return self;
299: }
300:
301: - forward: (SEL) sel : (marg_list) args
302: {
303: return [self doesNotRecognize: sel];
304: }
305:
306: /* this method is not part of the published API */
307:
308: - (unsigned)methodArgSize:(SEL)sel
309: {
310: Method method = class_getInstanceMethod((Class)isa, sel);
311: if (! method) return 0;
312: return method_getSizeOfArguments(method);
313: }
314:
315: - performv: (SEL) sel : (marg_list) args
316: {
317: unsigned size;
318: #if hppa && 0
319: void *ret;
320:
321: // Save ret0 so methods that return a struct might work.
322: asm("copy %%r28, %0": "=r"(ret): );
323: #endif hppa
324:
325: if (! self) return nil;
326: size = [self methodArgSize: sel];
327: if (! size) return [self doesNotRecognize: sel];
328:
329: #if hppa && 0
330: // Unfortunately, it looks like the compiler puts something else in
331: // r28 right after this instruction, so this is all for naught.
332: asm("copy %0, %%r28": : "r"(ret));
333: #endif hppa
334:
335: return objc_msgSendv (self, sel, size, args);
336: }
337:
338: /* Testing protocol conformance */
339:
340: - (BOOL) conformsTo: (Protocol *)aProtocolObj
341: {
342: return [isa conformsTo:aProtocolObj];
343: }
344:
345: + (BOOL) conformsTo: (Protocol *)aProtocolObj
346: {
347: Class class;
348:
349: for (class = self; class; class = class->super_class)
350: {
351: if (class->isa->version >= 3)
352: {
353: struct objc_protocol_list *protocols = class->protocols;
354:
355: while (protocols)
356: {
357: int i;
358:
359: for (i = 0; i < protocols->count; i++)
360: {
361: Protocol *p = protocols->list[i];
362:
363: if ([p conformsTo:aProtocolObj])
364: return YES;
365: }
366:
367: if (class->isa->version <= 4)
368: break;
369:
370: protocols = protocols->next;
371: }
372: }
373: }
374: return NO;
375: }
376:
377: #if hppa && 0
378: #define OBJC_REMOTE_SIGN_BUG 1
379: #endif
380:
381: #if OBJC_REMOTE_SIGN_BUG
382: /*
383: * The problem being worked around here is the one where NextStep DO
384: * (actually ObjC) can't handle minus signs in method descriptor strings sent
385: * by HP clients. We remove them here, but this code returns the wrong
386: * answer for local clients.
387: *
388: * The bug needs to get fixed in NextStep. This workaround is really ugly.
389: */
390: static char *
391: stripsigns(char *str)
392: {
393: char *dst;
394: char *src;
395:
396: if (str) {
397: dst = src = str;
398: while (*src) {
399: if (*src == '-') {
400: src++; /* skip minus sign */
401: } else {
402: *dst++ = *src++; /* copy */
403: }
404: }
405: *dst = 0;
406: }
407: return (str);
408: }
409: #endif /* OBJC_REMOTE_SIGN_BUG */
410:
411: /* Looking up information for a method */
412:
413: - (struct objc_method_description *) descriptionForMethod:(SEL)aSelector
414: {
415: Class cls;
416: struct objc_method_description *m;
417:
418: /* Look in the protocols first. */
419: for (cls = isa; cls; cls = cls->super_class)
420: {
421: if (cls->isa->version >= 3)
422: {
423: struct objc_protocol_list *protocols = cls->protocols;
424:
425: while (protocols)
426: {
427: int i;
428:
429: for (i = 0; i < protocols->count; i++)
430: {
431: Protocol *p = protocols->list[i];
432:
433: if (ISMETA (cls))
434: m = [p descriptionForClassMethod:aSelector];
435: else
436: m = [p descriptionForInstanceMethod:aSelector];
437:
438: if (m) {
439: #if OBJC_REMOTE_SIGN_BUG
440: #warning "Working around OBJC_REMOTE_SIGN_BUG"
441: m->types = stripsigns(m->types);
442: #endif /* OBJC_REMOTE_SIGN_BUG */
443: return m;
444: }
445: }
446:
447: if (cls->isa->version <= 4)
448: break;
449:
450: protocols = protocols->next;
451: }
452: }
453: }
454:
455: /* Then try the class implementations. */
456: for (cls = isa; cls; cls = cls->super_class)
457: {
458: struct objc_method_list *methods;
459:
460: for (methods = cls->methods; methods; methods = methods->method_next)
461: {
462: int i;
463:
464: for (i = 0; i < methods->method_count; i++)
465: if (methods->method_list[i].method_name == aSelector) {
466: m = (struct objc_method_description *)
467: &methods->method_list[i];
468: #if OBJC_REMOTE_SIGN_BUG
469: m->types = stripsigns(m->types);
470: #endif /* OBJC_REMOTE_SIGN_BUG */
471: return (m);
472: }
473: }
474: }
475:
476: return 0;
477: }
478:
479: + (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSelector
480: {
481: Class cls;
482:
483: /* Look in the protocols first. */
484: for (cls = self; cls; cls = cls->super_class)
485: {
486: if (cls->isa->version >= 3)
487: {
488: struct objc_protocol_list *protocols = cls->protocols;
489:
490: while (protocols)
491: {
492: int i;
493:
494: for (i = 0; i < protocols->count; i++)
495: {
496: Protocol *p = protocols->list[i];
497: struct objc_method_description *m;
498:
499: if ((m = [p descriptionForInstanceMethod:aSelector]))
500: return m;
501: }
502:
503: if (cls->isa->version <= 4)
504: break;
505:
506: protocols = protocols->next;
507: }
508: }
509: }
510:
511: /* Then try the class implementations. */
512: for (cls = self; cls; cls = cls->super_class)
513: {
514: struct objc_method_list *methods;
515:
516: for (methods = cls->methods; methods; methods = methods->method_next)
517: {
518: int i;
519:
520: for (i = 0; i < methods->method_count; i++)
521: if (methods->method_list[i].method_name == aSelector)
522: return (struct objc_method_description *)
523: &methods->method_list[i];
524: }
525: }
526:
527: return 0;
528: }
529:
530:
531: /* Obsolete methods (for binary compatibility only). */
532:
533: + superClass
534: {
535: return [self superclass];
536: }
537:
538: - superClass
539: {
540: return [self superclass];
541: }
542:
543: - (BOOL)isKindOfGivenName:(const char *)aClassName
544: {
545: return [self isKindOfClassNamed: aClassName];
546: }
547:
548: - (BOOL)isMemberOfGivenName:(const char *)aClassName
549: {
550: return [self isMemberOfClassNamed: aClassName];
551: }
552:
553: - (struct objc_method_description *) methodDescFor:(SEL)aSelector
554: {
555: return [self descriptionForMethod: aSelector];
556: }
557:
558: + (struct objc_method_description *) instanceMethodDescFor:(SEL)aSelector
559: {
560: return [self descriptionForInstanceMethod: aSelector];
561: }
562:
563: - findClass:(const char *)aClassName
564: {
565: return (*_cvtToId)(aClassName);
566: }
567:
568: - shouldNotImplement:(SEL)aSelector
569: {
570: return [self error:_errShouldNotImp, sel_getName(aSelector)];
571: }
572:
573: @end
574:
575: /* System Primitive...declared as `private externs' in shared library */
576:
577: id _internal_object_copyFromZone(Object *anObject, unsigned nBytes, NXZone *zone)
578: {
579: id obj;
580: register unsigned siz;
581:
582: if (anObject == nil)
583: return nil;
584:
585: obj = (*_zoneAlloc)(anObject->isa, nBytes, zone);
586: siz = anObject->isa->instance_size + nBytes;
587: bcopy(anObject, obj, siz);
588: return obj;
589: }
590:
591: id _internal_object_copy(Object *anObject, unsigned nBytes)
592: {
593: NXZone *zone = NXZoneFromPtr(anObject);
594: return _internal_object_copyFromZone(anObject,
595: nBytes,
596: zone ? zone : NXDefaultMallocZone());
597: }
598:
599: id _internal_object_dispose(Object *anObject)
600: {
601: if (anObject==nil) return nil;
602: anObject->isa = _objc_getFreedObjectClass ();
603: free(anObject);
604: return nil;
605: }
606:
607: id _internal_object_reallocFromZone(Object *anObject, unsigned nBytes, NXZone *zone)
608: {
609: Object *newObject;
610: Class tmp;
611:
612: if (anObject == nil)
613: __objc_error(nil, _errReAllocNil, 0);
614:
615: if (anObject->isa == _objc_getFreedObjectClass ())
616: __objc_error(anObject, _errReAllocFreed, 0);
617:
618: if (nBytes < ((Class)anObject->isa)->instance_size)
619: __objc_error(anObject, _errReAllocTooSmall,
620: object_getClassName(anObject), nBytes);
621:
622: // Make sure not to modify space that has been declared free
623: tmp = anObject->isa;
624: anObject->isa = _objc_getFreedObjectClass ();
625: newObject = (id)NXZoneRealloc(zone, anObject, nBytes);
626: if (newObject) {
627: newObject->isa = tmp;
628: return newObject;
629: }
630: else
631: {
632: __objc_error(anObject, _errNoMem,
633: object_getClassName(anObject), nBytes);
634: return nil;
635: }
636: }
637:
638: id _internal_object_realloc(Object *anObject, unsigned nBytes)
639: {
640: NXZone *zone = NXZoneFromPtr(anObject);
641: return _internal_object_reallocFromZone(anObject,
642: nBytes,
643: zone ? zone : NXDefaultMallocZone());
644: }
645:
646: /* Functional Interface to system primitives */
647:
648: id object_copy(Object *anObject, unsigned nBytes)
649: {
650: return (*_copy)(anObject, nBytes);
651: }
652:
653: id object_copyFromZone(Object *anObject, unsigned nBytes, NXZone *zone)
654: {
655: return (*_zoneCopy)(anObject, nBytes, zone);
656: }
657:
658: id object_dispose(Object *anObject)
659: {
660: return (*_dealloc)(anObject);
661: }
662:
663: id object_realloc(Object *anObject, unsigned nBytes)
664: {
665: return (*_realloc)(anObject, nBytes);
666: }
667:
668: id object_reallocFromZone(Object *anObject, unsigned nBytes, NXZone *zone)
669: {
670: return (*_zoneRealloc)(anObject, nBytes, zone);
671: }
672:
673: Ivar object_setInstanceVariable(id obj, const char *name, void *value)
674: {
675: Ivar ivar = 0;
676:
677: if (obj && name) {
678: void **ivaridx;
679:
680: if ((ivar = class_getInstanceVariable(((Object*)obj)->isa, name))) {
681: ivaridx = (void **)((char *)obj + ivar->ivar_offset);
682: *ivaridx = value;
683: }
684: }
685: return ivar;
686: }
687:
688: Ivar object_getInstanceVariable(id obj, const char *name, void **value)
689: {
690: Ivar ivar = 0;
691:
692: if (obj && name) {
693: void **ivaridx;
694:
695: if ((ivar = class_getInstanceVariable(((Object*)obj)->isa, name))) {
696: ivaridx = (void **)((char *)obj + ivar->ivar_offset);
697: *value = *ivaridx;
698: } else
699: *value = 0;
700: }
701: return ivar;
702: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.