|
|
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.