Artifact 5c7645fb2af658d4db801a48459a6d92260ccf045ad9b71845f0e3229b9d5b46:
- File
src/runtime/lookup.m
— part of check-in
[ef6d69931e]
at
2019-02-07 00:46:41
on branch trunk
— Make style consistent between ObjFW and ObjFW_RT
ObjFW_RT used to be a separate project that followed the BSD style, as
it was written in pure C, while ObjFW's style is based on the BSD style
with changes to make it a better fit for Objective-C. This commit
changes ObjFW_RT to use the same style as ObjFW. (user: js, size: 4932) [annotate] [blame] [check-ins using]
/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, * 2018, 2019 * Jonathan Schleifer <js@heap.zone> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" #include <stdio.h> #include <stdlib.h> #import "ObjFW_RT.h" #import "private.h" #import "macros.h" @interface DummyObject { Class isa; } + (bool)resolveClassMethod: (SEL)selector; + (bool)resolveInstanceMethod: (SEL)selector; @end static IMP forwardHandler = (IMP)0; static IMP stretForwardHandler = (IMP)0; static IMP commonMethodNotFound(id object, SEL selector, IMP (*lookup)(id, SEL), IMP forward) { /* * object might be a dummy object (see class_getMethodImplementation), * so don't access object directly unless it's a class! */ bool isClass = object_getClass(object)->info & OBJC_CLASS_INFO_METACLASS; if (!(object_getClass(object)->info & OBJC_CLASS_INFO_INITIALIZED)) { Class cls = (isClass ? (Class)object : object_getClass(object)); objc_initialize_class(cls); if (!(cls->info & OBJC_CLASS_INFO_SETUP)) OBJC_ERROR("Could not dispatch message for incomplete " "class %s!", cls->name); /* * We don't need to handle the case that super was called. * The reason for this is that a call to super is not possible * before a message to the class has been sent and it thus has * been initialized together with its superclasses. */ return lookup(object, selector); } /* Try resolveClassMethod: / resolveInstanceMethod: */ if (class_isMetaClass(object_getClass(object))) { Class cls = object_getClass(object); if (class_respondsToSelector(cls, @selector(resolveClassMethod:)) && [object resolveClassMethod: selector]) { if (!class_respondsToSelector(cls, selector)) OBJC_ERROR("[%s resolveClassMethod: %s] " "returned true without adding the method!", class_getName(object), sel_getName(selector)); return lookup(object, selector); } } else { Class cls = object_getClass(object); Class metaclass = object_getClass(cls); if (class_respondsToSelector(metaclass, @selector(resolveInstanceMethod:)) && [cls resolveInstanceMethod: selector]) { if (!class_respondsToSelector(cls, selector)) OBJC_ERROR("[%s resolveInstanceMethod: %s] " "returned true without adding the method!", class_getName(object_getClass(object)), sel_getName(selector)); return lookup(object, selector); } } if (forward != (IMP)0) return forward; OBJC_ERROR("Selector %c[%s] is not implemented for class %s!", (isClass ? '+' : '-'), sel_getName(selector), object_getClassName(object)); } IMP objc_method_not_found(id object, SEL selector) { return commonMethodNotFound(object, selector, objc_msg_lookup, forwardHandler); } IMP objc_method_not_found_stret(id object, SEL selector) { return commonMethodNotFound(object, selector, objc_msg_lookup_stret, stretForwardHandler); } void objc_setForwardHandler(IMP forward, IMP stretForward) { forwardHandler = forward; stretForwardHandler = stretForward; } bool class_respondsToSelector(Class cls, SEL selector) { if (cls == Nil) return false; return (objc_dtable_get(cls->DTable, (uint32_t)selector->UID) != (IMP)0); } #ifndef OF_ASM_LOOKUP static id nilMethod(id self, SEL _cmd) { return nil; } static OF_INLINE IMP commonLookup(id object, SEL selector, IMP (*notFound)(id, SEL)) { IMP imp; if (object == nil) return (IMP)nilMethod; imp = objc_dtable_get(object_getClass(object)->DTable, (uint32_t)selector->UID); if (imp == (IMP)0) return notFound(object, selector); return imp; } IMP objc_msg_lookup(id object, SEL selector) { return commonLookup(object, selector, objc_method_not_found); } IMP objc_msg_lookup_stret(id object, SEL selector) { return commonLookup(object, selector, objc_method_not_found_stret); } static OF_INLINE IMP commonSuperLookup(struct objc_super *super, SEL selector, IMP (*notFound)(id, SEL)) { IMP imp; if (super->self == nil) return (IMP)nilMethod; imp = objc_dtable_get(super->cls->DTable, (uint32_t)selector->UID); if (imp == (IMP)0) return notFound(super->self, selector); return imp; } IMP objc_msg_lookup_super(struct objc_super *super, SEL selector) { return commonSuperLookup(super, selector, objc_method_not_found); } IMP objc_msg_lookup_super_stret(struct objc_super *super, SEL selector) { return commonSuperLookup(super, selector, objc_method_not_found_stret); } #endif