/* 
   objc-runtime.h

   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
   All rights reserved.

   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>

   This file is part of the Foundation Extensions Library.

   Permission to use, copy, modify, and distribute this software and its
   documentation for any purpose and without fee is hereby granted, provided
   that the above copyright notice appear in all copies and that both that
   copyright notice and this permission notice appear in supporting
   documentation.

   We disclaim all warranties with regard to this software, including all
   implied warranties of merchantability and fitness, in no event shall
   we be liable for any special, indirect or consequential damages or any
   damages whatsoever resulting from loss of use, data or profits, whether in
   an action of contract, negligence or other tortious action, arising out of
   or in connection with the use or performance of this software.
*/

#ifndef __objc_runtime_h__
#define __objc_runtime_h__

#if !defined(GNU_RUNTIME) && !defined(NeXT_RUNTIME)
# error You should define the runtime flag! Try adding
# error to ADDITIONAL_CPPFLAGS in the Makefile.preamble
# error file the $(RUNTIME_DEFINE) variable like this:
# error ADDITIONAL_CPPFLAGS += $(RUNTIME_DEFINE)
#endif

#if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 6) && !defined(__attribute__)
#  define __attribute__(x)
#endif

#include <objc/objc.h>


extern BOOL sel_types_match(const char*, const char*);

#if GNU_RUNTIME

#include <objc/objc-api.h>
#include <objc/Protocol.h>
#include <objc/encoding.h>

#define class_addMethods	class_add_methods
#define SEL_EQ(sel1, sel2)	sel_eq(sel1, sel2)

#else /* NeXT_RUNTIME */

#include <objc/objc-class.h>
#include <extensions/objc-api.h>
#include <extensions/encoding.h>

#define SEL_EQ(sel1, sel2)	(sel1 == sel2)

extern BOOL sel_isMapped(SEL sel);
extern const char *sel_getName(SEL sel);
extern SEL sel_getUid(const char *str);
extern SEL sel_registerName(const char *str);
extern const char *object_getClassName(id obj);

extern id class_createInstance(Class, unsigned idxIvars);

extern void class_setVersion(Class, int);
extern int class_getVersion(Class);

extern struct objc_method* class_getInstanceMethod(Class, SEL);
extern struct objc_method* class_getClassMethod(Class, SEL);

extern Class class_poseAs(Class imposter, Class original);
extern id objc_lookUpClass(const char *name);

#define class_get_class_method		class_getClassMethod
#define class_get_instance_method	class_getInstanceMethod
#define class_pose_as			class_poseAs
#define objc_get_class			objc_getClass
#define objc_lookup_class		objc_lookUpClass
#define sel_get_name			sel_getName
#define sel_get_uid			sel_getUid
#define sel_get_any_uid			sel_getUid
#define sel_register_name		sel_registerName
#define sel_is_mapped			sel_isMapped
#define class_create_instance(CLASS) \
	class_createInstance(CLASS, 0)
#define class_set_version		class_setVersion
#define class_get_version		class_getVersion
#define object_get_class_name		object_getClassName

#define objc_msg_lookup			objc_msgLookup
#define objc_msg_sendv			next_objc_msg_sendv

extern id objc_msgSend(id self, SEL op, ...);
extern id objc_msgSendSuper(struct objc_super *super, SEL op, ...);

extern id next_objc_msg_sendv(id self, SEL op, void* arg_frame);

static inline IMP
objc_msgLookup(id object, SEL sel)
{
    if(!object || !sel) return NULL;
    else {
	Class class = object->class_pointer;
	struct objc_method* mth =
	    (CLS_ISCLASS(class) ?
		  class_get_instance_method(class, sel)
		: class_get_class_method(class, sel));
	return mth ? mth->method_imp : (IMP)0;
    }
}

#endif /* NeXT_RUNTIME */


extern void class_addMethods(Class, struct objc_method_list*);
void class_add_behavior(Class class, Class behavior);

#endif /* __objc_runtime_h__ */
