/* GNU Objective-C Runtime API.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995 Free Software Foundation, Inc.
This file is part of GNU CC.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* As a special exception, if you link this library with files compiled
with GCC to produce an executable, this does not cause the resulting
#ifndef __objc_api_INCLUDE_GNU
#define __objc_api_INCLUDE_GNU
-#include <stdlib.h>
-#include <objc/objc.h>
-
-static const ARGSIZE = 96; /* for `method_get_argsize()' */
+#include "objc/objc.h"
+#include "objc/hash.h"
+#include <stdio.h>
+/* For functions which return Method_t */
+#define METHOD_NULL (Method_t)0
+ /* Boolean typedefs */
/*
-** Points to the function that the runtime system calls to handle
-** an error. By default, it prints formatted error messages to the
-** standard error stream and calls abort to produce a core file.
-** The function is guaranteed to be passed a valid object and a
-** non-NULL format string.
+** Method descriptor returned by introspective Object methods.
+** This is really just the first part of the more complete objc_method
+** structure defined below and used internally by the runtime.
*/
-extern void (*_objc_error)(id object, const char *format, va_list args);
+struct objc_method_description
+{
+ SEL name; /* this is a selector, not a string */
+ char *types; /* type encoding */
+};
+
+/* Filer types used to describe Ivars and Methods. */
+#define _C_ID '@'
+#define _C_CLASS '#'
+#define _C_SEL ':'
+#define _C_CHR 'c'
+#define _C_UCHR 'C'
+#define _C_SHT 's'
+#define _C_USHT 'S'
+#define _C_INT 'i'
+#define _C_UINT 'I'
+#define _C_LNG 'l'
+#define _C_ULNG 'L'
+#define _C_FLT 'f'
+#define _C_DBL 'd'
+#define _C_BFLD 'b'
+#define _C_VOID 'v'
+#define _C_UNDEF '?'
+#define _C_PTR '^'
+#define _C_CHARPTR '*'
+#define _C_ATOM '%'
+#define _C_ARY_B '['
+#define _C_ARY_E ']'
+#define _C_UNION_B '('
+#define _C_UNION_E ')'
+#define _C_STRUCT_B '{'
+#define _C_STRUCT_E '}'
+
+
+
+/*
+** Set this variable nonzero to print a line describing each
+** message that is sent. (this is currently disabled)
+*/
+extern BOOL objc_trace;
+
+
+/*
+** Whereas a Module (defined further down) is the root (typically) of a file,
+** a Symtab is the root of the class and category definitions within the
+** module.
+**
+** A Symtab contains a variable length array of pointers to classes and
+** categories defined in the module.
+*/
+typedef struct objc_symtab {
+ unsigned long sel_ref_cnt; /* Unknown. */
+ SEL refs; /* Unknown. */
+ unsigned short cls_def_cnt; /* Number of classes compiled
+ (defined) in the module. */
+ unsigned short cat_def_cnt; /* Number of categories
+ compiled (defined) in the
+ module. */
+ void *defs[1]; /* Variable array of pointers.
+ cls_def_cnt of type Class
+ followed by cat_def_cnt of
+ type Category_t. */
+} Symtab, *Symtab_t;
+
+
+/* For every class which happens to have statically allocated instances in
+ this module, one OBJC_STATIC_INSTANCES is allocated by the compiler.
+ INSTANCES is NULL terminated and points to all statically allocated
+ instances of this class. */
+struct objc_static_instances
+{
+ char *class_name;
+ id instances[0];
+};
/*
-** This is a hook which is called by objc_lookup_class and
-** objc_get_class if the runtime is not able to find the class.
-** This may e.g. try to load in the class using dynamic loading.
-** The function is guaranteed to be passed a non-NULL name string.
-*/
-extern Class_t (*_objc_lookup_class)(const char *name);
+** The compiler generates one of these structures for each module that
+** composes the executable (eg main.m).
+**
+** This data structure is the root of the definition tree for the module.
+**
+** A collect program runs between ld stages and creates a ObjC ctor array.
+** That array holds a pointer to each module structure of the executable.
+*/
+typedef struct objc_module {
+ unsigned long version; /* Compiler revision. */
+ unsigned long size; /* sizeof(Module). */
+ const char* name; /* Name of the file where the
+ module was generated. The
+ name includes the path. */
+
+ /* Pointer to a NULL terminated array of objc_static_instances. */
+ struct objc_static_instances **statics;
+
+ Symtab_t symtab; /* Pointer to the Symtab of
+ the module. The Symtab
+ holds an array of pointers to
+ the classes and categories
+ defined in the module. */
+} Module, *Module_t;
+
+
+/*
+** The compiler generates one of these structures for a class that has
+** instance variables defined in its specification.
+*/
+typedef struct objc_ivar* Ivar_t;
+typedef struct objc_ivar_list {
+ int ivar_count; /* Number of structures (Ivar)
+ contained in the list. One
+ structure per instance
+ variable defined in the
+ class. */
+ struct objc_ivar {
+ const char* ivar_name; /* Name of the instance
+ variable as entered in the
+ class definition. */
+ const char* ivar_type; /* Description of the Ivar's
+ type. Useful for
+ debuggers. */
+ int ivar_offset; /* Byte offset from the base
+ address of the instance
+ structure to the variable. */
+
+ } ivar_list[1]; /* Variable length
+ structure. */
+} IvarList, *IvarList_t;
+
+
+/*
+** The compiler generates one (or more) of these structures for a class that
+** has methods defined in its specification.
+**
+** The implementation of a class can be broken into separate pieces in a file
+** and categories can break them across modules. To handle this problem is a
+** singly linked list of methods.
+*/
+typedef struct objc_method Method;
+typedef Method* Method_t;
+typedef struct objc_method_list {
+ struct objc_method_list* method_next; /* This variable is used to link
+ a method list to another. It
+ is a singly linked list. */
+ int method_count; /* Number of methods defined in
+ this structure. */
+ struct objc_method {
+ SEL method_name; /* This variable is the method's
+ name. It is a char*.
+ The unique integer passed to
+ objc_msg_send is a char* too.
+ It is compared against
+ method_name using strcmp. */
+ const char* method_types; /* Description of the method's
+ parameter list. Useful for
+ debuggers. */
+ IMP method_imp; /* Address of the method in the
+ executable. */
+ } method_list[1]; /* Variable length
+ structure. */
+} MethodList, *MethodList_t;
-/*
-** Points to the function that the runtime system calls to allocate
-** memory for new instances. Called through class_create_instance(),
-** this function should return a valid block of memory of at least
-** class_get_instance_size() bytes, or nil upon failure. The
-** function is guaranteed to be passed a valid class object.
-*/
-extern id (*_objc_object_alloc)(Class_t class);
+struct objc_protocol_list {
+ struct objc_protocol_list *next;
+ int count;
+ Protocol *list[1];
+};
/*
-** Points to the function that the runtime system calls to create
-** an exact copy of an object. Called through object_copy(), this
-** function should return a new instance of object's class created
-** by class_create_instance() which is bit-identical to object, or
-** nil upon failure. The function is guaranteed to be passed a
-** valid instance object.
+** This is used to assure consistent access to the info field of
+** classes
*/
-extern id (*_objc_object_copy)(id object);
+#ifndef HOST_BITS_PER_LONG
+#define HOST_BITS_PER_LONG (sizeof(long)*8)
+#endif
+
+#define __CLS_INFO(cls) ((cls)->info)
+#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls)&mask)==mask)
+#define __CLS_SETINFO(cls, mask) (__CLS_INFO(cls) |= mask)
+
+/* The structure is of type MetaClass */
+#define _CLS_META 0x2L
+#define CLS_ISMETA(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_META))
+
+
+/* The structure is of type Class */
+#define _CLS_CLASS 0x1L
+#define CLS_ISCLASS(cls) ((cls)&&__CLS_ISINFO(cls, _CLS_CLASS))
/*
-** Points to the function that the runtime system calls to free
-** instances. Called through object_dispose(), this function
-** should free the memory pointed to by object and return nil.
-** This function is not responsible for freeing memory pointed
-** to by any of the object's instance variables. The function
-** is guaranteed to be passed a valid instance object.
+** The class is initialized within the runtime. This means that
+** it has had correct super and sublinks assigned
*/
-extern id (*_objc_object_dispose)(id object);
+#define _CLS_RESOLV 0x8L
+#define CLS_ISRESOLV(cls) __CLS_ISINFO(cls, _CLS_RESOLV)
+#define CLS_SETRESOLV(cls) __CLS_SETINFO(cls, _CLS_RESOLV)
/*
-** Searches for a class method specified by aSel, starting with the
-** metaclass class and proceeding up the class hierarchy, until either
-** the method is found or the root class has been examined. Returns
-** a pointer to the method's Method structure if found. Returns the
-** value METHOD_NULL if the method is not found, class is not a
-** metaclass object, or aSel is not a valid selector.
+** The class has been send a +initialize message or a such is not
+** defined for this class
*/
-Method_t class_get_class_method(MetaClass_t class, SEL aSel);
+#define _CLS_INITIALIZED 0x04L
+#define CLS_ISINITIALIZED(cls) __CLS_ISINFO(cls, _CLS_INITIALIZED)
+#define CLS_SETINITIALIZED(cls) __CLS_SETINFO(cls, _CLS_INITIALIZED)
/*
-** Searches for an instance method specified by aSel, starting with
-** the class class and proceeding up the class hierarchy, until either
-** the method is found or the root class has been examined. Returns
-** a pointer to the method's Method structure if found. Returns the
-** value METHOD_NULL if the method is not found, class is not a class
-** object, or aSel is not a valid selector.
+** The class number of this class. This must be the same for both the
+** class and it's meta class object
*/
-Method_t class_get_instance_method(Class_t class, SEL aSel);
+#define CLS_GETNUMBER(cls) (__CLS_INFO(cls) >> (HOST_BITS_PER_LONG/2))
+#define CLS_SETNUMBER(cls, num) \
+ ({ (cls)->info <<= (HOST_BITS_PER_LONG/2); \
+ (cls)->info >>= (HOST_BITS_PER_LONG/2); \
+ __CLS_SETINFO(cls, (((unsigned long)num) << (HOST_BITS_PER_LONG/2))); })
/*
-** Causes impostor to pose as its superclass. Messages sent to the
-** superclass will actually be sent to the posing class. Instance
-** variables may not be declared in the posing class. The posing
-** class can add new methods to the class or override existing methods
-** in the superclass. Returns non-nil on success. Returns nil if
-** either of impostor or superclass are not class objects, impostor is
-** not a subclass of superclass, or upon some other error.
+** The compiler generates one of these structures for each category. A class
+** may have many categories and contain both instance and factory methods.
*/
-Class_t class_pose_as(Class_t impostor, Class_t superclass);
+typedef struct objc_category {
+ const char* category_name; /* Name of the category. Name
+ contained in the () of the
+ category definition. */
+ const char* class_name; /* Name of the class to which
+ the category belongs. */
+ MethodList_t instance_methods; /* Linked list of instance
+ methods defined in the
+ category. NULL indicates no
+ instance methods defined. */
+ MethodList_t class_methods; /* Linked list of factory
+ methods defined in the
+ category. NULL indicates no
+ class methods defined. */
+ struct objc_protocol_list *protocols; /* List of Protocols
+ conformed to */
+} Category, *Category_t;
/*
-** Returns the class object for the class named name. If name does not
-** identify a known class, the hook _objc_lookup_class is called. If
-** this fails, an error message is issued and the system aborts.
+** Structure used when a message is send to a class's super class. The
+** compiler generates one of these structures and passes it to
+** objc_msg_super.
*/
-Class_t objc_get_class(const char *name);
+typedef struct objc_super {
+ id self; /* Id of the object sending
+ the message. */
+ Class class; /* Object's super class. */
+} Super, *Super_t;
+
+IMP objc_msg_lookup_super(Super_t super, SEL sel);
+
+retval_t objc_msg_sendv(id, SEL, arglist_t);
+
+
/*
-** Returns the class object for the class named name. If name does not
-** identify a known class, the hook _objc_lookup_class is called. If
-** this fails, nil is returned.
+** This is a hook which is called by objc_lookup_class and
+** objc_get_class if the runtime is not able to find the class.
+** This may e.g. try to load in the class using dynamic loading.
+** The function is guaranteed to be passed a non-NULL name string.
*/
-Class_t objc_lookup_class(const char *name);
+extern Class (*_objc_lookup_class)(const char *name);
/*
-** Returns the method name associated with selector, or NULL
-** if selector is not defined.
+** This is a hook which is called by __objc_exec_class every time a class
+** or a category is loaded into the runtime. This may e.g. help a
+** dynamic loader determine the classes that have been loaded when
+** an object file is dynamically linked in.
*/
+extern void (*_objc_load_callback)(Class class, Category* category);
+
+extern id (*_objc_object_alloc)(Class class);
+
+extern id (*_objc_object_copy)(id object);
+
+extern id (*_objc_object_dispose)(id object);
+
+Method_t class_get_class_method(MetaClass class, SEL aSel);
+
+Method_t class_get_instance_method(Class class, SEL aSel);
+
+Class class_pose_as(Class impostor, Class superclass);
+
+Class objc_get_class(const char *name);
+
+Class objc_lookup_class(const char *name);
+
+Class objc_next_class(void **enum_state);
+
const char *sel_get_name(SEL selector);
-/*
-** Returns the selector associated with the method name name. If name
-** has not been defined or name is NULL, 0 is returned.
-*/
+const char *sel_get_type(SEL selector);
+
SEL sel_get_uid(const char *name);
-/*
-** Registers a selector for name and returns the new selector. If
-** name is NULL or the empty string (""), 0 is returned.
-*/
+SEL sel_get_any_uid(const char *name);
+
+SEL sel_get_any_typed_uid(const char *name);
+
+SEL sel_get_typed_uid(const char *name, const char*);
+
SEL sel_register_name(const char *name);
-/*
-** Indicate if aSel is a valid selector. This is not a safe
-** operation, and it should really never be nessecary to use.
-*/
-BOOL sel_is_mapped (SEL aSel);
+SEL sel_register_typed_name(const char *name, const char*type);
-/*******************************************************************/
-/* */
-/* Internal __inline functions */
-/* */
-/*******************************************************************/
-/*
-** Allocates memory for a new object of class class by calling the
-** function specified by the variable _objc_object_alloc if non-zero,
-** otherwise uses a default method. Then, initializes the object's
-** isa instance variable to class, and returns the new object.
-** Returns nil if the memory could not be allocated or class is not
-** a class object.
-*/
-extern inline id
-class_create_instance(Class_t class)
-{
- id new = nil;
- if (CLS_ISCLASS(class))
- new = (_objc_object_alloc
- ?(*_objc_object_alloc)(class)
- :(id)malloc(class->instance_size));
- if (new!=nil)
- new->class_pointer = class;
- return new;
-}
+BOOL sel_is_mapped (SEL aSel);
+
+extern id class_create_instance(Class class);
-/*
-** Returns name of the class class or empty string if class is not
-** a class object. If class is Nil, the string "Nil" is returned.
-*/
static inline const char *
-class_get_class_name(Class_t class)
+class_get_class_name(Class class)
{
return CLS_ISCLASS(class)?class->name:((class==Nil)?"Nil":0);
}
-/*
-** Returns the size of an instance of class class in bytes, or 0 if
-** class is not a class. The size of an instance is at least 4 bytes.
-*/
static inline long
-class_get_instance_size(Class_t class)
+class_get_instance_size(Class class)
{
return CLS_ISCLASS(class)?class->instance_size:0;
}
-/*
-** Returns a pointer to class's metaclass, or Nil if class is not a
-** class.
-*/
-static inline MetaClass_t
-class_get_meta_class(Class_t class)
+static inline MetaClass
+class_get_meta_class(Class class)
{
return CLS_ISCLASS(class)?class->class_pointer:Nil;
}
-/*
-** Returns a pointer to class's superclass, or Nil if class is not a
-** class. Note that the superclass of Object is Nil.
-*/
-static inline Class_t
-class_get_super_class(Class_t class)
+static inline Class
+class_get_super_class(Class class)
{
return CLS_ISCLASS(class)?class->super_class:Nil;
}
-/*
-** Returns the version number for the class, or -1 if class is not a
-** class.
-*/
static inline int
-class_get_version(Class_t class)
+class_get_version(Class class)
{
return CLS_ISCLASS(class)?class->version:-1;
}
-/*
-** Returns YES if class is a class, or NO if not.
-*/
static inline BOOL
-class_is_class(Class_t class)
+class_is_class(Class class)
{
return CLS_ISCLASS(class);
}
-/*
-** Returns YES if class is a metaclass, or NO if not.
-*/
static inline BOOL
-class_is_meta_class(Class_t class)
+class_is_meta_class(Class class)
{
return CLS_ISMETA(class);
}
-/*
-** Sets the version number of class class. Does nothing if class is
-** not a class.
-*/
static inline void
-class_set_version(Class_t class, long version)
+class_set_version(Class class, long version)
{
if (CLS_ISCLASS(class))
class->version = version;
}
-/*
-** Returns the size in bytes of the argument frame to a method. Since
-** at least two parameters (self and _cmd) are sent to each method, this
-** value will be at least 8. If method is not a valid method, 0 is
-** returned.
-**
-** Currently, the frame size info is only reliable on a NeXT, so until
-** we get this fixed, we'll use a value which is most possibly large
-** enough. You can possibly reduce this value (96) on anything but a
-** Sparc if you don't return structs from the methods forwarded to.
-*/
-static inline unsigned int
-method_get_argsize(Method_t method)
-{
- return ARGSIZE; /* This was a magic number (96)... */
-}
-
-/*
-** Returns a pointer to the implementation of method method. If method
-** is not a method, NULL is returned.
-*/
static inline IMP
method_get_imp(Method_t method)
{
return (method!=METHOD_NULL)?method->method_imp:(IMP)0;
}
-/*
-** Returns the implementation (pointer to function) of the method
-** identified by a (class, selector) pair. Use this, and *not*
-** objc_msg_lookup, since objc_msg_lookup may eventually return a
-** pointer to an internal function which does lazy initialization...
-*/
-IMP get_imp (Class_t class, SEL sel);
+IMP get_imp (Class class, SEL sel);
-/*
-** Creates a new instance object that's an exact copy of object by
-** calling the function pointed to by the variable _objc_object_copy if
-** non-zero, otherwise uses a default method. Returns the new object.
-** Returns nil if object is not an instance object, memory for the new
-** object could not be allocated, or some other error occurred.
-*/
-extern inline id
-object_copy(id object)
-{
- if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
- {
- if (_objc_object_copy)
- return (*_objc_object_copy)(object);
- else
- {
- id copy = class_create_instance(object->class_pointer);
- if (copy!=nil)
- bcopy(object, copy, object->class_pointer->instance_size);
- return copy;
- }
- return nil;
- }
-}
+id object_copy(id object);
-/*
-** Frees the memory occupied by object by calling the function pointed
-** to by the variable _objc_object_dispose if non-zero, otherwise uses
-** a default method. Always returns nil. If object is not an instance
-** object, does nothing.
-*/
-extern inline id
-object_dispose(id object)
-{
- if ((object!=nil)&&CLS_ISCLASS(object->class_pointer))
- {
- if (_objc_object_dispose)
- (*_objc_object_dispose)(object);
- else
- free(object);
- }
- return nil;
-}
+id object_dispose(id object);
-/*
-** Returns the class of an object. If object is an instance, this is
-** its class object. If object is a class object, returns object (this
-** is arguably not correct, but is implemented this way for compatibility
-** with NeXT (and Stepstone?)). If object is a metaclass object, or
-** object is nil, returns Nil.
-*/
-static inline Class_t
+static inline Class
object_get_class(id object)
{
return ((object!=nil)
? (CLS_ISCLASS(object->class_pointer)
? object->class_pointer
: (CLS_ISMETA(object->class_pointer)
- ? (Class_t)object
+ ? (Class)object
: Nil))
: Nil);
}
-/*
-** Returns the name of the class of object. If object is an instace,
-** this is the name of its class. If object is a class or a metaclass,
-** returns its name. If object is nil, returns "Nil".
-*/
static inline const char *
object_get_class_name(id object)
{
return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
?object->class_pointer->name
- :((Class_t)object)->name)
+ :((Class)object)->name)
:"Nil");
}
-/*
-** Returns the metaclass of an object. If object is an instance or a
-** class, this is the metaclass object for it. If object is a metaclass
-** object, or object is nil, returns Nil.
-*/
-static inline MetaClass_t
+static inline MetaClass
object_get_meta_class(id object)
{
return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
:Nil);
}
-/*
-** Returns the superclass of object. If object is an instance or
-** a class, this is its superclass-object for it. If object is a
-** metaclass-object or nil, this is Nil.
-*/
-static inline Class_t
-object_get_super_class(id object)
+static inline Class
+object_get_super_class
+(id object)
{
return ((object!=nil)?(CLS_ISCLASS(object->class_pointer)
?object->class_pointer->super_class
:(CLS_ISMETA(object->class_pointer)
- ?((Class_t)object)->super_class
+ ?((Class)object)->super_class
:Nil))
:Nil);
}
-/*
-** YES if object is a class, NO if not.
-*/
static inline BOOL
object_is_class(id object)
{
- return CLS_ISCLASS((Class_t)object);
+ return CLS_ISCLASS((Class)object);
}
-/*
-** YES if object is an instance, NO if not.
-*/
static inline BOOL
object_is_instance(id object)
{
return (object!=nil)&&CLS_ISCLASS(object->class_pointer);
}
-/*
-** YES if object is a metaclass, NO if not.
-*/
static inline BOOL
object_is_meta_class(id object)
{
- return CLS_ISMETA((Class_t)object);
+ return CLS_ISMETA((Class)object);
}
-/*
-** Functions used for archiving. This is not documented yet!
-*/
-
-TypedStream* new_typed_stream(FILE* physical);
-void free_typed_stream(TypedStream* stream);
+#endif /* not __objc_api_INCLUDE_GNU */
-void objc_write_object(TypedStream* stream, id object);
-int objc_read_object(TypedStream* stream, id *object);
-void objc_write_type(TypedStream* stream, const char* type, const void* data);
-void objc_read_type(TypedStream* stream, const char* type, void* data);
-#endif /* not __objc_api_INCLUDE_GNU */