[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: AmigaOS dynamic loading support
- From: Steven Solie <ssolie@...>
- Date: Sun, 26 Mar 2006 15:59:28 -0600
On 26/03/2006, Luiz Henrique de Figueiredo wrote:
>> There are a couple of things worth noting about this patch: 1. Lua's
>> Node type conflicts with AmigaOS's Node type in the loadlib.c file so
>> I renamed Node -> TNode in Lua to work around the problem.
>
> I think you can just add the line below to luaconf.h:
> `#define Node TNode
> There is no need to patch the other files.
> Please give it a try.
Good idea but I think I've found an even better way to work
around the problem. I just define Node in loadlib.c but only
for the Amiga platform and then undef it again. This works
just as well.
I've attached an updated patch which should be much more
to your liking.
--Steven
diff -ruN lua-5.1/amiga/amigalua_lib.c lua-5.1-2/amiga/amigalua_lib.c
--- lua-5.1/amiga/amigalua_lib.c Thu Jan 01 00:00:00 1970
+++ lua-5.1-2/amiga/amigalua_lib.c Sun Mar 26 09:15:41 2006
@@ -0,0 +1,273 @@
+/*
+** This is a basic implementation of an AmigaOS dynamic Lua library.
+**
+** The setup is the same as any shared library except we add an additional
+** interface named "lua" of type LuaIFace to your library.
+**
+** Lua libraries also require a minimal amount of C library support which
+** is provided using clib2's shared library accessibility feature. It
+** should be possible to use the newlib C library as well with some effort.
+**
+*/
+
+#include <dos/dos.h>
+#include <proto/dos.h>
+#include <proto/exec.h>
+
+#include "lauxlib.h"
+
+#include <string.h>
+
+
+/*---------------------------------------------------------------------------*/
+#define LIBNAME "amigalua.library"
+#define LIBPRI 0
+#define LIBVER 1
+#define LIBREV 0
+#define LIBVSTR LIBNAME" 1.0 (25.3.2006)" /* dd.mm.yyyy */
+
+static const char* __attribute__((used)) vtag = "$VER: "LIBVSTR;
+
+
+/*---------------------------------------------------------------------------*/
+struct AmigaLuaBase {
+ struct Library libNode;
+ BPTR segList;
+ struct ExecIFace* iexec;
+};
+
+
+struct LuaIFace {
+ struct InterfaceData Data;
+
+ uint32 APICALL (*Obtain)(struct LuaIFace *Self);
+ uint32 APICALL (*Release)(struct LuaIFace *Self);
+ void APICALL (*Expunge)(struct LuaIFace *Self);
+ struct Interface * APICALL (*Clone)(struct LuaIFace* Self);
+ lua_CFunction APICALL (*GetFunctionAddress)(struct LuaIFace* Self,
+ const char* symbol);
+};
+
+
+/*---------------------------------------------------------------------------*/
+BOOL __lib_init(struct Library*);
+void __lib_exit();
+
+struct AmigaLuaBase* libInit(struct AmigaLuaBase*, BPTR, struct ExecIFace*);
+uint32 libObtain(struct LibraryManagerInterface*);
+uint32 libRelease(struct LibraryManagerInterface*);
+struct AmigaLuaBase* libOpen(struct LibraryManagerInterface*, uint32);
+BPTR libClose(struct LibraryManagerInterface*);
+BPTR libExpunge(struct LibraryManagerInterface*);
+
+uint32 _Lua_Obtain(struct LuaIFace*);
+uint32 _Lua_Release(struct LuaIFace*);
+lua_CFunction _Lua_GetFunctionAddress(struct LuaIFace*, const char*);
+
+
+/*---------------------------------------------------------------------------*/
+static APTR libManagerVectors[] = {
+ libObtain,
+ libRelease,
+ NULL,
+ NULL,
+ libOpen,
+ libClose,
+ libExpunge,
+ NULL,
+ (APTR)-1
+};
+
+
+static struct TagItem libManagerTags[] = {
+ {MIT_Name, (uint32)"__library"},
+ {MIT_VectorTable, (uint32)libManagerVectors},
+ {MIT_Version, 1},
+ {MIT_DataSize, 0},
+ {TAG_END, 0}
+};
+
+
+static APTR libLuaVectors[] = {
+ _Lua_Obtain,
+ _Lua_Release,
+ NULL,
+ NULL,
+ _Lua_GetFunctionAddress,
+ (APTR)-1
+};
+
+
+static struct TagItem libLuaTags[] = {
+ {MIT_Name, (uint32)"lua"},
+ {MIT_VectorTable, (uint32)libLuaVectors},
+ {MIT_Version, 1},
+ {MIT_DataSize, 0},
+ {TAG_END, 0}
+};
+
+
+static APTR libInterfaces[] = {
+ libManagerTags,
+ libLuaTags,
+ NULL
+};
+
+
+static struct TagItem libCreateTags[] = {
+ {CLT_DataSize, sizeof(struct AmigaLuaBase)},
+ {CLT_InitFunc, (uint32)libInit},
+ {CLT_Interfaces, (uint32)libInterfaces},
+ {TAG_END, 0}
+};
+
+
+static struct Resident __attribute__((used)) libResident = {
+ RTC_MATCHWORD, // rt_MatchWord
+ &libResident, // rt_MatchTag
+ &libResident + 1, // rt_EndSkip
+ RTF_NATIVE | RTF_AUTOINIT, // rt_Flags
+ LIBVER, // rt_Version
+ NT_LIBRARY, // rt_Type
+ LIBPRI, // rt_Pri
+ LIBNAME, // rt_Name
+ LIBVSTR, // rt_IdString
+ libCreateTags // rt_Init
+};
+
+
+/*---------------------------------------------------------------------------*/
+int32 _start()
+{
+ return RETURN_FAIL;
+}
+
+
+/*---------------------------------------------------------------------------*/
+struct AmigaLuaBase* libInit(struct AmigaLuaBase* libBase, BPTR seglist,
+ struct ExecIFace* ISys)
+{
+ libBase->libNode.lib_Node.ln_Type = NT_LIBRARY;
+ libBase->libNode.lib_Node.ln_Pri = LIBPRI;
+ libBase->libNode.lib_Node.ln_Name = LIBNAME;
+ libBase->libNode.lib_Flags = LIBF_SUMUSED | LIBF_CHANGED;
+ libBase->libNode.lib_Version = LIBVER;
+ libBase->libNode.lib_Revision = LIBREV;
+ libBase->libNode.lib_IdString = LIBVSTR;
+ libBase->segList = seglist;
+ libBase->iexec = ISys;
+
+ /* Initializes clib2 so we can access the C library */
+ if ( __lib_init(ISys->Data.LibBase) ) {
+ return libBase;
+ }
+
+ return NULL;
+}
+
+
+uint32 libObtain(struct LibraryManagerInterface* Self)
+{
+ return ++Self->Data.RefCount;
+}
+
+
+uint32 libRelease(struct LibraryManagerInterface* Self)
+{
+ return --Self->Data.RefCount;
+}
+
+
+struct AmigaLuaBase* libOpen(struct LibraryManagerInterface* Self,
+ uint32 version)
+{
+ struct AmigaLuaBase* libBase = (struct AmigaLuaBase*)Self->Data.LibBase;
+
+ ++libBase->libNode.lib_OpenCnt;
+ libBase->libNode.lib_Flags &= ~LIBF_DELEXP;
+
+ return libBase;
+}
+
+
+BPTR libClose(struct LibraryManagerInterface* Self)
+{
+ struct AmigaLuaBase* libBase = (struct AmigaLuaBase*)Self->Data.LibBase;
+
+ --libBase->libNode.lib_OpenCnt;
+
+ if ( libBase->libNode.lib_OpenCnt > 0 ) {
+ return 0;
+ }
+
+ if ( libBase->libNode.lib_Flags & LIBF_DELEXP ) {
+ return (BPTR)Self->LibExpunge();
+ }
+ else {
+ return 0;
+ }
+}
+
+
+BPTR libExpunge(struct LibraryManagerInterface* Self)
+{
+ BPTR result = 0;
+
+ struct AmigaLuaBase* libBase = (struct AmigaLuaBase*)Self->Data.LibBase;
+
+ if ( libBase->libNode.lib_OpenCnt == 0 ) {
+ /* Concludes access to clib2 C library */
+ __lib_exit();
+
+ result = libBase->segList;
+
+ libBase->iexec->Remove(&libBase->libNode.lib_Node);
+ libBase->iexec->DeleteLibrary(&libBase->libNode);
+ }
+ else {
+ libBase->libNode.lib_Flags |= LIBF_DELEXP;
+ }
+
+ return result;
+}
+
+
+/*---------------------------------------------------------------------------*/
+uint32 _Lua_Obtain(struct LuaIFace* Self)
+{
+ return ++Self->Data.RefCount;
+}
+
+
+uint32 _Lua_Release(struct LuaIFace* Self)
+{
+ return --Self->Data.RefCount;
+}
+
+
+lua_CFunction _Lua_GetFunctionAddress(struct LuaIFace* Self,
+ const char* symbol)
+{
+ extern const volatile struct luaL_reg amigaLuaLib[];
+
+ if ( symbol != 0 ) {
+ const volatile struct luaL_reg* entry = 0;
+ for ( entry = amigaLuaLib; entry->name != 0; ++entry ) {
+ if ( strcmp(symbol, entry->name) == 0 ) {
+ return entry->func;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/*---------------------------------------------------------------------------*/
+void _init()
+{
+}
+
+void _fini()
+{
+}
diff -ruN lua-5.1/amiga/amigalua_lua.c lua-5.1-2/amiga/amigalua_lua.c
--- lua-5.1/amiga/amigalua_lua.c Thu Jan 01 00:00:00 1970
+++ lua-5.1-2/amiga/amigalua_lua.c Sun Mar 26 15:38:45 2006
@@ -0,0 +1,86 @@
+/*
+** This file contains the Lua specific functions. Once the library has
+** been opened and the functions are registered they are accessible from
+** the Lua client.
+**
+*/
+
+#include <proto/dos.h>
+#include <proto/exec.h>
+
+#include "lauxlib.h"
+
+#include <string.h>
+
+
+/*---------------------------------------------------------------------------*/
+int l_luaopen(lua_State*);
+int l_processList(lua_State*);
+int l_print(lua_State*);
+
+
+/*---------------------------------------------------------------------------*/
+
+/* The luaLib array may be read by more than one process at a time. */
+const volatile struct luaL_reg amigaLuaLib[] = {
+ {"luaopen_amiga", l_luaopen},
+ {0, 0}
+};
+
+
+static const struct luaL_reg luaLib[] = {
+ {"processList", l_processList},
+ {"print", l_print},
+ {NULL, NULL}
+};
+
+
+int l_luaopen(lua_State* L)
+{
+ luaL_register(L, "amiga", luaLib);
+ return 1;
+}
+
+
+/*---------------------------------------------------------------------------*/
+int32 hookFunc(struct Hook* h, uint32* counter, struct Process* p)
+{
+ IDOS->Printf("%-40s %6lu %6lu %7lu\n",
+ p->pr_Task.tc_Node.ln_Name,
+ p->pr_ProcessID,
+ p->pr_ParentID,
+ p->pr_StackSize);
+
+ (*counter)++;
+
+ return 0;
+}
+
+
+int l_processList(lua_State* L)
+{
+ IDOS->Printf("%-40s %6s %6s %7s\n",
+ "Name",
+ "PID",
+ "PPID",
+ "Stack");
+
+ struct Hook hook;
+ memset(&hook, 0, sizeof(struct Hook));
+ hook.h_Entry = (HOOKFUNC)&hookFunc;
+
+ uint32 total = 0;
+
+ IDOS->ProcessScan(&hook, &total, 0);
+
+ lua_pushnumber(L, total);
+ return 1;
+}
+
+
+int l_print(lua_State* L)
+{
+ const char* s = luaL_checkstring(L, 1);
+ IDOS->Printf("%s\n", s);
+ return 0;
+}
diff -ruN lua-5.1/amiga/Makefile lua-5.1-2/amiga/Makefile
--- lua-5.1/amiga/Makefile Thu Jan 01 00:00:00 1970
+++ lua-5.1-2/amiga/Makefile Sun Mar 26 10:27:18 2006
@@ -0,0 +1,19 @@
+#
+# Makefile for AmigaOS Lua dynamic loading test
+#
+
+.PHONY: clean
+
+CFLAGS := -Wall -mcrt=clib2-ts -I../src
+LIBS := -llua -lm -lc -lunix -lgcc
+OBJS := amigalua_lib.o amigalua_lua.o
+
+amigalua.library: $(OBJS)
+ gcc $(CFLAGS) -nostartfiles -nostdlib -o $@ -L../src $^ $(LIBS)
+ avail flush >NIL:
+
+clean:
+ -delete $(OBJS)
+
+%.o: %.c
+ gcc $(CFLAGS) -c $^
diff -ruN lua-5.1/amiga/test.lua lua-5.1-2/amiga/test.lua
--- lua-5.1/amiga/test.lua Thu Jan 01 00:00:00 1970
+++ lua-5.1-2/amiga/test.lua Sun Mar 26 15:21:29 2006
@@ -0,0 +1,10 @@
+--
+-- Tests the dynamic library loading feature
+--
+local path = "amigalua.library"
+local f = assert( package.loadlib(path, "luaopen_amiga") )
+f();
+
+amiga.print("List of processes:")
+total = amiga.processList()
+io.write(total," total processes\n")
diff -ruN lua-5.1/Makefile lua-5.1-2/Makefile
--- lua-5.1/Makefile Thu Feb 16 08:45:17 2006
+++ lua-5.1-2/Makefile Sun Mar 26 09:26:24 2006
@@ -37,7 +37,7 @@
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
# Convenience platforms targets.
-PLATS= aix ansi bsd generic linux macosx mingw posix solaris
+PLATS= aix amigaos ansi bsd generic linux macosx mingw posix solaris
# What to install.
TO_BIN= lua luac
diff -ruN lua-5.1/src/loadlib.c lua-5.1-2/src/loadlib.c
--- lua-5.1/src/loadlib.c Thu Dec 29 08:32:11 2005
+++ lua-5.1-2/src/loadlib.c Sun Mar 26 15:53:14 2006
@@ -226,6 +226,66 @@
+#elif defined(LUA_DL_AMIGA)
+/*
+** {======================================================================
+** Native AmigaOS Implementation
+**
+** All Amiga libraries which are compatible with Lua implement the
+** LuaIFace as defined below.
+**
+** Note that IExec must be setup prior to loading any Lua library.
+** =======================================================================
+*/
+
+#define Node AmigaNode
+#include <proto/exec.h>
+#undef AmigaNode
+
+
+struct LuaIFace {
+ struct InterfaceData Data;
+
+ uint32 APICALL (*Obtain)(struct LuaIFace *Self);
+ uint32 APICALL (*Release)(struct LuaIFace *Self);
+ void APICALL (*Expunge)(struct LuaIFace *Self);
+ struct Interface * APICALL (*Clone)(struct LuaIFace* Self);
+ void * APICALL (*GetFunctionAddress)(struct LuaIFace *Self,
+ const char *symbol);
+};
+
+
+static void ll_unloadlib (void *lib) {
+ struct Interface *ilua = (struct Interface*)lib;
+ struct Library *base = ilua->Data.LibBase;
+ IExec->DropInterface(ilua);
+ IExec->CloseLibrary(base);
+}
+
+
+static void *ll_load (lua_State *L, const char *path) {
+ struct Library *base = IExec->OpenLibrary(path, 0);
+ struct Interface *ilua = IExec->GetInterface(base, "lua", 1, 0);
+ if (ilua == NULL) {
+ lua_pushfstring(L, "cannot open library " LUA_QS, path);
+ }
+ return ilua;
+}
+
+
+static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+ struct LuaIFace* ilua = (struct LuaIFace*)lib;
+ lua_CFunction f = ilua->GetFunctionAddress(sym); /* sym may be null */
+ if (f == NULL) {
+ lua_pushfstring(L, "symbol " LUA_QS " not found", sym);
+ }
+ return f;
+}
+
+/* }====================================================== */
+
+
+
#else
/*
** {======================================================
diff -ruN lua-5.1/src/luaconf.h lua-5.1-2/src/luaconf.h
--- lua-5.1/src/luaconf.h Fri Feb 10 10:44:06 2006
+++ lua-5.1-2/src/luaconf.h Sun Mar 26 14:31:25 2006
@@ -44,6 +44,9 @@
#define LUA_DL_DYLD /* does not need extra library */
#endif
+#if defined(__amigaos__)
+#define LUA_DL_AMIGA
+#endif
/*
@@ -171,7 +174,7 @@
#define LUAI_DATA /* empty */
#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
- defined(__ELF__)
+ defined(__ELF__) && !defined(__amigaos__)
#define LUAI_FUNC __attribute__((visibility("hidden"))) extern
#define LUAI_DATA LUAI_FUNC
@@ -731,6 +734,4 @@
*/
-
#endif
-
diff -ruN lua-5.1/src/Makefile lua-5.1-2/src/Makefile
--- lua-5.1/src/Makefile Thu Feb 16 08:45:09 2006
+++ lua-5.1-2/src/Makefile Sun Mar 26 09:19:26 2006
@@ -20,7 +20,7 @@
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
-PLATS= aix ansi bsd generic linux macosx mingw posix solaris
+PLATS= aix amigaos ansi bsd generic linux macosx mingw posix solaris
LUA_A= liblua.a
CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
@@ -81,6 +81,9 @@
aix:
$(MAKE) all CC="xlc" CFLAGS="-O2" MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall"
+
+amigaos:
+ $(MAKE) all MYCFLAGS="-mcrt=clib2-ts -DLUA_USE_ISATTY -DLUA_USE_POPEN" MYLDFLAGS=-mcrt=clib2-ts MYLIBS=-lunix
ansi:
$(MAKE) all MYCFLAGS=-DLUA_ANSI