/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
* 2018
* 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"
#import "ObjFW_RT.h"
#import "macros.h"
#define BOOL EXEC_BOOL
#include <dos/dos.h>
#include <emul/emulregs.h>
#include <exec/execbase.h>
#include <exec/nodes.h>
#include <exec/resident.h>
#include <exec/types.h>
#include <proto/exec.h>
#undef BOOL
struct ObjFWRTBase {
struct Library library;
BPTR seg_list;
};
/* Forward declarations for all functions in the func_table */
static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list,
struct ExecBase *exec_base);
static struct Library *lib_open(void);
static BPTR lib_close(void);
static BPTR lib_expunge(void);
static void lib_null(void);
void objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status));
static ULONG func_table[] = {
FUNCARRAY_BEGIN,
FUNCARRAY_32BIT_NATIVE,
(ULONG)lib_open,
(ULONG)lib_close,
(ULONG)lib_expunge,
(ULONG)lib_null,
-1,
FUNCARRAY_32BIT_SYSTEMV,
/* Functions for the glue code */
(ULONG)objc_set_exit,
/* Used by the compiler - these need glue code */
(ULONG)__objc_exec_class,
(ULONG)objc_msg_lookup,
(ULONG)objc_msg_lookup_stret,
(ULONG)objc_msg_lookup_super,
(ULONG)objc_msg_lookup_super_stret,
(ULONG)objc_lookUpClass,
(ULONG)objc_getClass,
(ULONG)objc_getRequiredClass,
(ULONG)objc_exception_throw,
(ULONG)objc_sync_enter,
(ULONG)objc_sync_exit,
(ULONG)objc_getProperty,
(ULONG)objc_setProperty,
(ULONG)objc_getPropertyStruct,
(ULONG)objc_setPropertyStruct,
(ULONG)objc_enumerationMutation,
/* Functions declared in ObjFW_RT.h */
(ULONG)sel_registerName,
(ULONG)sel_getName,
(ULONG)sel_isEqual,
(ULONG)objc_allocateClassPair,
(ULONG)objc_registerClassPair,
(ULONG)objc_getClassList,
(ULONG)objc_copyClassList,
(ULONG)class_isMetaClass,
(ULONG)class_getName,
(ULONG)class_getSuperclass,
(ULONG)class_getInstanceSize,
(ULONG)class_respondsToSelector,
(ULONG)class_conformsToProtocol,
(ULONG)class_getMethodImplementation,
(ULONG)class_getMethodImplementation_stret,
(ULONG)class_getMethodTypeEncoding,
(ULONG)class_addMethod,
(ULONG)class_replaceMethod,
(ULONG)object_getClass,
(ULONG)object_setClass,
(ULONG)object_getClassName,
(ULONG)protocol_getName,
(ULONG)protocol_isEqual,
(ULONG)protocol_conformsToProtocol,
(ULONG)objc_exit,
(ULONG)objc_setUncaughtExceptionHandler,
(ULONG)objc_setForwardHandler,
(ULONG)objc_setEnumerationMutationHandler,
(ULONG)objc_zero_weak_references,
-1,
FUNCARRAY_END
};
static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list,
struct ExecBase *exec_base);
static struct {
LONG struct_size;
ULONG *func_table;
void *data_table;
struct Library *(*init_func)(struct ObjFWRTBase *base, BPTR seg_list,
struct ExecBase *exec_base);
} init_table = {
.struct_size = sizeof(struct ObjFWRTBase),
func_table,
NULL,
lib_init
};
static struct Resident resident = {
.rt_MatchWord = RTC_MATCHWORD,
.rt_MatchTag = &resident,
.rt_EndSkip = &resident + 1,
.rt_Flags = RTF_AUTOINIT | RTF_PPC,
.rt_Version = OBJFW_RT_LIB_MAJOR * 10 + OBJFW_RT_LIB_MINOR,
.rt_Type = NT_LIBRARY,
.rt_Pri = 0,
.rt_Name = (char *)"objfw_rt.library",
.rt_IdString = (char *)"ObjFW_RT " PACKAGE_VERSION
" \xA9 2008-2018 Jonathan Schleifer",
.rt_Init = &init_table
};
/* Magic required to make this a MorphOS binary */
const ULONG __abox__ = 1;
/* Global variables needed by libnix */
int ThisRequiresConstructorHandling;
struct ExecBase *SysBase;
void *libnix_mempool;
/* Functions passed in from the glue linklib */
static void OF_NO_RETURN_FUNC (*exit_fn)(int status);
void OF_NO_RETURN_FUNC
exit(int status)
{
exit_fn(status);
}
void
objc_set_exit(void OF_NO_RETURN_FUNC (*exit_fn_)(int status))
{
exit_fn = exit_fn_;
}
/* Standard library functions */
static struct Library *lib_init(struct ObjFWRTBase *base, BPTR seg_list,
struct ExecBase *exec_base)
{
SysBase = exec_base;
base->seg_list = seg_list;
return &base->library;
}
static struct Library *
lib_open(void)
{
struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6;
base->library.lib_OpenCnt++;
base->library.lib_Flags &= ~LIBF_DELEXP;
return &base->library;
}
static BPTR
expunge(struct ObjFWRTBase *base)
{
/* Still in use - set delayed expunge flag and refuse to expunge */
if (base->library.lib_OpenCnt > 0) {
base->library.lib_Flags |= LIBF_DELEXP;
return 0;
}
Remove(&base->library.lib_Node);
FreeMem((char *)base - base->library.lib_NegSize,
base->library.lib_NegSize + base->library.lib_PosSize);
return base->seg_list;
}
static BPTR
lib_close(void)
{
struct ObjFWRTBase *base = (struct ObjFWRTBase *)REG_A6;
/* Not used anymore and delayed expunge flag set -> expunge */
if (--base->library.lib_OpenCnt == 0 &&
(base->library.lib_Flags & LIBF_DELEXP))
return expunge(base);
return 0;
}
static BPTR
lib_expunge(void)
{
return expunge((struct ObjFWRTBase *)REG_A6);
}
static void
lib_null(void)
{
}