lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Attached is a patch to add dynamic loading to Lua 5.1 for AmigaOS.

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.

2. I added an amiga directory which contains code to test the
dynamic loading feature. This would be optional as I see no other
platform (e.g. Windows) has an example in the official distribution.

Comments are appreciated.

P.S. I'd be happy to be put on as maintainer for the AmigaOS port.

--Steven Solie
diff -ruN lua-5.1/amiga/amigalua_lib.c lua-5.1-1/amiga/amigalua_lib.c
--- lua-5.1/amiga/amigalua_lib.c	Thu Jan 01 00:00:00 1970
+++ lua-5.1-1/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-1/amiga/amigalua_lua.c
--- lua-5.1/amiga/amigalua_lua.c	Thu Jan 01 00:00:00 1970
+++ lua-5.1-1/amiga/amigalua_lua.c	Sat Mar 25 19:07:25 2006
@@ -0,0 +1,80 @@
+#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);
+	IDOS->Printf("Total %lu processes\n", total);
+
+	return 0;
+}
+
+
+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-1/amiga/Makefile
--- lua-5.1/amiga/Makefile	Thu Jan 01 00:00:00 1970
+++ lua-5.1-1/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-1/amiga/test.lua
--- lua-5.1/amiga/test.lua	Thu Jan 01 00:00:00 1970
+++ lua-5.1-1/amiga/test.lua	Sat Mar 25 18:46:27 2006
@@ -0,0 +1,9 @@
+--
+-- Tests the dynamic library loading feature
+--
+local path = "amigalua.library"
+local f = assert( package.loadlib(path, "luaopen_amiga") )
+f();
+
+amiga.print("List of processes:")
+amiga.processList()
diff -ruN lua-5.1/Makefile lua-5.1-1/Makefile
--- lua-5.1/Makefile	Thu Feb 16 08:45:17 2006
+++ lua-5.1-1/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/lgc.c lua-5.1-1/src/lgc.c
--- lua-5.1/src/lgc.c	Thu Dec 22 09:19:56 2005
+++ lua-5.1-1/src/lgc.c	Sat Mar 25 09:47:37 2006
@@ -59,7 +59,7 @@
 #define setthreshold(g)  (g->GCthreshold = (g->estimate/100) * g->gcpause)
 
 
-static void removeentry (Node *n) {
+static void removeentry (TNode *n) {
   lua_assert(ttisnil(gval(n)));
   if (iscollectable(gkey(n)))
     setttype(gkey(n), LUA_TDEADKEY);  /* dead key; remove it */
@@ -182,7 +182,7 @@
   }
   i = sizenode(h);
   while (i--) {
-    Node *n = gnode(h, i);
+    TNode *n = gnode(h, i);
     lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
     if (ttisnil(gval(n)))
       removeentry(n);  /* remove empty entries */
@@ -285,7 +285,7 @@
       if (traversetable(g, h))  /* table is weak? */
         black2gray(o);  /* keep it gray */
       return sizeof(Table) + sizeof(TValue) * h->sizearray +
-                             sizeof(Node) * sizenode(h);
+                             sizeof(TNode) * sizenode(h);
     }
     case LUA_TFUNCTION: {
       Closure *cl = gco2cl(o);
@@ -361,7 +361,7 @@
     }
     i = sizenode(h);
     while (i--) {
-      Node *n = gnode(h, i);
+      TNode *n = gnode(h, i);
       if (!ttisnil(gval(n)) &&  /* non-empty entry? */
           (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
         setnilvalue(gval(n));  /* remove value ... */
diff -ruN lua-5.1/src/loadlib.c lua-5.1-1/src/loadlib.c
--- lua-5.1/src/loadlib.c	Thu Dec 29 08:32:11 2005
+++ lua-5.1-1/src/loadlib.c	Sun Mar 26 09:22:16 2006
@@ -226,6 +226,64 @@
 
 
 
+#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.
+** =======================================================================
+*/
+
+#include <proto/exec.h>
+
+
+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/lobject.h lua-5.1-1/src/lobject.h
--- lua-5.1/src/lobject.h	Wed Jan 18 04:37:34 2006
+++ lua-5.1-1/src/lobject.h	Sat Mar 25 09:47:16 2006
@@ -323,16 +323,16 @@
 typedef union TKey {
   struct {
     TValuefields;
-    struct Node *next;  /* for chaining */
+    struct TNode *next;  /* for chaining */
   } nk;
   TValue tvk;
 } TKey;
 
 
-typedef struct Node {
+typedef struct TNode {
   TValue i_val;
   TKey i_key;
-} Node;
+} TNode;
 
 
 typedef struct Table {
@@ -341,8 +341,8 @@
   lu_byte lsizenode;  /* log2 of size of `node' array */
   struct Table *metatable;
   TValue *array;  /* array part */
-  Node *node;
-  Node *lastfree;  /* any free position is before this position */
+  TNode *node;
+  TNode *lastfree;  /* any free position is before this position */
   GCObject *gclist;
   int sizearray;  /* size of `array' array */
 } Table;
diff -ruN lua-5.1/src/ltable.c lua-5.1-1/src/ltable.c
--- lua-5.1/src/ltable.c	Wed Jan 18 04:49:02 2006
+++ lua-5.1-1/src/ltable.c	Sat Mar 25 09:49:06 2006
@@ -72,7 +72,7 @@
 
 #define dummynode		(&dummynode_)
 
-static const Node dummynode_ = {
+static const TNode dummynode_ = {
   {{NULL}, LUA_TNIL},  /* value */
   {{{NULL}, LUA_TNIL, NULL}}  /* key */
 };
@@ -81,7 +81,7 @@
 /*
 ** hash for lua_Numbers
 */
-static Node *hashnum (const Table *t, lua_Number n) {
+static TNode *hashnum (const Table *t, lua_Number n) {
   unsigned int a[numints];
   int i;
   n += 1;  /* normalize number (avoid -0) */
@@ -97,7 +97,7 @@
 ** returns the `main' position of an element in a table (that is, the index
 ** of its hash value)
 */
-static Node *mainposition (const Table *t, const TValue *key) {
+static TNode *mainposition (const Table *t, const TValue *key) {
   switch (ttype(key)) {
     case LUA_TNUMBER:
       return hashnum(t, nvalue(key));
@@ -141,7 +141,7 @@
   if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */
     return i-1;  /* yes; that's the index (corrected to C) */
   else {
-    Node *n = mainposition(t, key);
+    TNode *n = mainposition(t, key);
     do {  /* check whether `key' is somewhere in the chain */
       /* key may be dead already, but it is ok to use it in `next' */
       if (luaO_rawequalObj(key2tval(n), key) ||
@@ -249,7 +249,7 @@
   int ause = 0;  /* summation of `nums' */
   int i = sizenode(t);
   while (i--) {
-    Node *n = &t->node[i];
+    TNode *n = &t->node[i];
     if (!ttisnil(gval(n))) {
       ause += countint(key2tval(n), nums);
       totaluse++;
@@ -272,7 +272,7 @@
 static void setnodevector (lua_State *L, Table *t, int size) {
   int lsize;
   if (size == 0) {  /* no elements to hash part? */
-    t->node = cast(Node *, dummynode);  /* use common `dummynode' */
+    t->node = cast(TNode *, dummynode);  /* use common `dummynode' */
     lsize = 0;
   }
   else {
@@ -281,9 +281,9 @@
     if (lsize > MAXBITS)
       luaG_runerror(L, "table overflow");
     size = twoto(lsize);
-    t->node = luaM_newvector(L, size, Node);
+    t->node = luaM_newvector(L, size, TNode);
     for (i=0; i<size; i++) {
-      Node *n = gnode(t, i);
+      TNode *n = gnode(t, i);
       gnext(n) = NULL;
       setnilvalue(gkey(n));
       setnilvalue(gval(n));
@@ -298,7 +298,7 @@
   int i;
   int oldasize = t->sizearray;
   int oldhsize = t->lsizenode;
-  Node *nold = t->node;  /* save old hash ... */
+  TNode *nold = t->node;  /* save old hash ... */
   if (nasize > oldasize)  /* array part must grow? */
     setarrayvector(L, t, nasize);
   /* create new hash part with appropriate size */
@@ -315,12 +315,12 @@
   }
   /* re-insert elements from hash part */
   for (i = twoto(oldhsize) - 1; i >= 0; i--) {
-    Node *old = nold+i;
+    TNode *old = nold+i;
     if (!ttisnil(gval(old)))
       setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
   }
   if (nold != dummynode)
-    luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
+    luaM_freearray(L, nold, twoto(oldhsize), TNode);  /* free old array */
 }
 
 
@@ -364,7 +364,7 @@
   t->array = NULL;
   t->sizearray = 0;
   t->lsizenode = 0;
-  t->node = cast(Node *, dummynode);
+  t->node = cast(TNode *, dummynode);
   setarrayvector(L, t, narray);
   setnodevector(L, t, nhash);
   return t;
@@ -373,13 +373,13 @@
 
 void luaH_free (lua_State *L, Table *t) {
   if (t->node != dummynode)
-    luaM_freearray(L, t->node, sizenode(t), Node);
+    luaM_freearray(L, t->node, sizenode(t), TNode);
   luaM_freearray(L, t->array, t->sizearray, TValue);
   luaM_free(L, t);
 }
 
 
-static Node *getfreepos (Table *t) {
+static TNode *getfreepos (Table *t) {
   while (t->lastfree-- > t->node) {
     if (ttisnil(gkey(t->lastfree)))
       return t->lastfree;
@@ -397,10 +397,10 @@
 ** position), new key goes to an empty position. 
 */
 static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
-  Node *mp = mainposition(t, key);
+  TNode *mp = mainposition(t, key);
   if (!ttisnil(gval(mp)) || mp == dummynode) {
-    Node *othern;
-    Node *n = getfreepos(t);  /* get a free place */
+    TNode *othern;
+    TNode *n = getfreepos(t);  /* get a free place */
     if (n == NULL) {  /* cannot find a free place? */
       rehash(L, t, key);  /* grow table */
       return luaH_set(L, t, key);  /* re-insert key into grown table */
@@ -438,7 +438,7 @@
     return &t->array[key-1];
   else {
     lua_Number nk = cast_num(key);
-    Node *n = hashnum(t, nk);
+    TNode *n = hashnum(t, nk);
     do {  /* check whether `key' is somewhere in the chain */
       if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
         return gval(n);  /* that's it */
@@ -453,7 +453,7 @@
 ** search function for strings
 */
 const TValue *luaH_getstr (Table *t, TString *key) {
-  Node *n = hashstr(t, key);
+  TNode *n = hashstr(t, key);
   do {  /* check whether `key' is somewhere in the chain */
     if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
       return gval(n);  /* that's it */
@@ -479,7 +479,7 @@
       /* else go through */
     }
     default: {
-      Node *n = mainposition(t, key);
+      TNode *n = mainposition(t, key);
       do {  /* check whether `key' is somewhere in the chain */
         if (luaO_rawequalObj(key2tval(n), key))
           return gval(n);  /* that's it */
@@ -579,10 +579,10 @@
 
 #if defined(LUA_DEBUG)
 
-Node *luaH_mainposition (const Table *t, const TValue *key) {
+TNode *luaH_mainposition (const Table *t, const TValue *key) {
   return mainposition(t, key);
 }
 
-int luaH_isdummy (Node *n) { return n == dummynode; }
+int luaH_isdummy (TNode *n) { return n == dummynode; }
 
 #endif
diff -ruN lua-5.1/src/ltable.h lua-5.1-1/src/ltable.h
--- lua-5.1/src/ltable.h	Tue Jan 10 06:13:06 2006
+++ lua-5.1-1/src/ltable.h	Sat Mar 25 09:47:49 2006
@@ -32,8 +32,8 @@
 
 
 #if defined(LUA_DEBUG)
-LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
-LUAI_FUNC int luaH_isdummy (Node *n);
+LUAI_FUNC TNode *luaH_mainposition (const Table *t, const TValue *key);
+LUAI_FUNC int luaH_isdummy (TNode *n);
 #endif
 
 
diff -ruN lua-5.1/src/luaconf.h lua-5.1-1/src/luaconf.h
--- lua-5.1/src/luaconf.h	Fri Feb 10 10:44:06 2006
+++ lua-5.1-1/src/luaconf.h	Sat Mar 25 11:46:09 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-1/src/Makefile
--- lua-5.1/src/Makefile	Thu Feb 16 08:45:09 2006
+++ lua-5.1-1/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