summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/BLua.cc298
-rw-r--r--lib/Handle.cc8
-rw-r--r--lib/LuaHandle.cc463
3 files changed, 758 insertions, 11 deletions
diff --git a/lib/BLua.cc b/lib/BLua.cc
index 286857e..18789f7 100644
--- a/lib/BLua.cc
+++ b/lib/BLua.cc
@@ -1,27 +1,38 @@
+#include <lualib.h>
#include "BLua.h"
-#ifndef LUAL_BUFFERSIZE
-#define LUAL_BUFFERSIZE BUFSIZ
+#ifndef BUFFERSIZE
+#define BUFFERSIZE 2048
#endif
+typedef GeneralException LuaException;
+
class LuaStatics : public Base {
public:
static const char * getF(lua_State *, void *, size_t *);
+ static int luapanic(lua_State *) throw(GeneralException);
+ static int destructor(lua_State *);
};
std::map<lua_State *, Lua *> Lua::lualist;
+int LuaStatics::luapanic(lua_State * L) throw (GeneralException) {
+ Lua::find(L)->showerror();
+ throw LuaException("Error running Lua code, bailing out.");
+}
+
Lua::Lua() : L(lua_open()) {
- // error setting ? **TODO**
+ lua_atpanic(L, LuaStatics::luapanic);
lualist[L] = this;
}
Lua::Lua(lua_State * _L) : L(_L) {
- // error setting ? **TODO**
+ lua_atpanic(L, LuaStatics::luapanic);
lualist[L] = this;
}
Lua::~Lua() {
+ lua_setgcthreshold(L, 0);
lua_close(L);
}
@@ -29,11 +40,58 @@ Lua::Lua(const Lua & l) throw (GeneralException) {
throw GeneralException("Error: can't duplicate a Lua object.");
}
+void Lua::open_base() {
+ luaopen_base(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_table() {
+ luaopen_table(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_io() {
+ luaopen_io(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_string() {
+ luaopen_string(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_math() {
+ luaopen_math(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_debug() {
+ luaopen_debug(L);
+ lua_pop(L, 1);
+}
+
+void Lua::declarefunc(const String & name, lua_CFunction f, int i) {
+ lua_pushstring(L, name.to_charp());
+ lua_pushcfunction(L, f);
+ lua_settable(L, i);
+}
+
+void Lua::call(const String & f, int i, int nargs, int nresults) {
+ lua_pushstring(L, f.to_charp());
+ lua_gettable(L, i);
+ lua_insert(L, -1 - nargs - nresults);
+ lua_call(L, nargs, nresults);
+}
+
+void Lua::call(int nargs, int nresults) {
+ lua_call(L, nargs, nresults);
+}
+
void Lua::push() {
lua_pushnil(L);
}
-void Lua::push(double n) {
+void Lua::push(lua_Number n) {
lua_pushnumber(L, n);
}
@@ -53,16 +111,111 @@ void Lua::push(lua_CFunction f, int n) {
lua_pushcclosure(L, f, n);
}
+void Lua::pop(int n) {
+ lua_pop(L, n);
+}
+
+void Lua::newtable() {
+ lua_newtable(L);
+}
+
+void Lua::settable(int i) {
+ lua_settable(L, i);
+}
+
+void Lua::gettable(int i) {
+ lua_gettable(L, i);
+}
+
+int Lua::gettop() {
+ return lua_gettop(L);
+}
+
+void Lua::error(const String & msg) {
+ push(msg);
+ lua_error(L);
+}
+
+int Lua::type(int i) {
+ return lua_type(L, i);
+}
+
+bool Lua::isnil(int i) {
+ return lua_isnil(L, i);
+}
+
+bool Lua::isboolean(int i) {
+ return lua_isboolean(L, i);
+}
+
+bool Lua::isnumber(int i) {
+ return lua_isnumber(L, i);
+}
+
+bool Lua::isstring(int i) {
+ return lua_isstring(L, i);
+}
+
+bool Lua::istable(int i) {
+ return lua_istable(L, i);
+}
+
+bool Lua::isfunction(int i) {
+ return lua_isfunction(L, i);
+}
+
+bool Lua::iscfunction(int i) {
+ return lua_iscfunction(L, i);
+}
+
+bool Lua::isuserdata(int i) {
+ return lua_isuserdata(L, i);
+}
+
+bool Lua::islightuserdata(int i) {
+ return lua_islightuserdata(L, i);
+}
+ bool toboolean(int = -1);
+ lua_Number tonumber(int = -1);
+ String tostring(int = -1);
+ lua_CFunction tocfunction(int = -1);
+ void * touserdata(int = -1);
+ Lua * tothread(int = -1);
+
+bool Lua::toboolean(int i) {
+ return lua_toboolean(L, i);
+}
+
+lua_Number Lua::tonumber(int i) {
+ return lua_tonumber(L, i);
+}
+
+String Lua::tostring(int i) {
+ return String(lua_tostring(L, i));
+}
+
+lua_CFunction Lua::tocfunction(int i) {
+ return lua_tocfunction(L, i);
+}
+
+void * Lua::touserdata(int i) {
+ return lua_touserdata(L, i);
+}
+
+Lua * Lua::tothread(int i) {
+ return find(lua_tothread(L, i));
+}
+
struct LoadF {
Handle * f;
- char buff[LUAL_BUFFERSIZE];
+ char buff[BUFFERSIZE];
};
const char * LuaStatics::getF(lua_State * L, void * ud, size_t * size) {
LoadF *lf = (LoadF *)ud;
(void)L;
- *size = lf->f->read(lf->buff, LUAL_BUFFERSIZE);
+ *size = lf->f->read(lf->buff, BUFFERSIZE);
return (*size > 0) ? lf->buff : NULL;
}
@@ -75,15 +228,138 @@ void Lua::load(Handle * h) throw (GeneralException) {
status = lua_load(L, LuaStatics::getF, &lf, h->GetName().to_charp());
if (status) {
- // displaying error **TODO**
- throw GeneralException("Error loading lua chunk `" + h->GetName() + "'");
+ showerror();
+ throw LuaException("Error loading lua chunk from Handle `" + h->GetName() + "'");
}
+
+ call();
}
Lua * Lua::thread() {
return new Lua(lua_newthread(L));
}
-Lua * Lua::find(lua_State * _L) {
- return lualist.find(_L)->second;
+Lua * Lua::find(lua_State * _L) throw (GeneralException) {
+ std::map<lua_State *, Lua *>::iterator i;
+
+ if ((i = lualist.find(_L)) == lualist.end()) {
+ throw GeneralException("Unable to find the Lua object for this context");
+ }
+
+ return i->second;
+}
+
+void Lua::showerror() {
+ int n = lua_gettop(L);
+ int i;
+ String t;
+
+ printm(M_ERROR, "Lua object: Got an LUA error\n");
+ printm(M_ERROR, "Inspecting LUA stack\n");
+
+ if (n == 0) {
+ printm(M_ERROR, "Stack empty\n");
+ return;
+ }
+
+ for (i = 1; i <= n; i++) {
+ switch(lua_type(L, i)) {
+ case LUA_TNONE:
+ t = "Invalid";
+ break;
+ case LUA_TNIL:
+ t = "(Nil)";
+ break;
+ case LUA_TNUMBER:
+ t.set("(Number) %f", lua_tonumber(L, i));
+ break;
+ case LUA_TBOOLEAN:
+ t.set("(Bool) %s", lua_toboolean(L, i) ? "true" : "false");
+ break;
+ case LUA_TSTRING:
+ t.set("(String) %s", lua_tostring(L, i));
+ break;
+ case LUA_TTABLE:
+ t = "(Table)";
+ break;
+ case LUA_TFUNCTION:
+ t = "(Function)";
+ break;
+ default:
+ t = "Unknown";
+ }
+
+ printm(M_ERROR, String(i) + ": " + t + "\n");
+ }
+}
+
+int Lua::getmetatable(int i) {
+ return lua_getmetatable(L, i);
+}
+
+int Lua::setmetatable(int i) {
+ return lua_setmetatable(L, i);
+}
+
+void LuaObject::push(Lua * L) throw (GeneralException) {
+ if (pushed && wantdestruct) {
+ throw GeneralException("Error: object is owned by the LUA script and can not be pushed.");
+ }
+ L->newtable();
+ pushmembers(L);
+ pushed = true;
+}
+
+void LuaObject::pushme(Lua * L, void * o) {
+ L->push("__obj");
+ L->push(o);
+ L->settable();
+}
+
+void * LuaObject::getme(Lua * L, int i) throw (GeneralException) {
+ void * r;
+
+ L->push("__obj");
+ L->gettable(i);
+ if (!(r = L->touserdata())) {
+ throw GeneralException("Lua object already destroyed");
+ }
+ L->pop();
+
+ return r;
+}
+
+void LuaObject::pushit(Lua * L, const String & s, lua_CFunction f) {
+ L->push(s);
+ L->push(f);
+ L->settable();
+}
+
+int LuaStatics::destructor(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ Base * b = (Base *) LuaObject::getme(L);
+ delete b;
+ L->push("__obj");
+ L->push((void *) 0);
+ L->settable();
+ printm(M_INFO, "Destructing an object from LUA\n");
+ return 0;
+}
+
+
+void LuaObject::pushdestruct(Lua * L) throw (GeneralException) {
+ if (pushed) {
+ throw GeneralException("Error: can't push destructor, object already pushed");
+ }
+ push(L);
+ if (!L->getmetatable(1)) {
+ L->newtable();
+ }
+ L->push("__gc");
+ L->push(LuaStatics::destructor);
+ L->settable();
+ L->setmetatable(1);
+ pushit(L, "destroy", LuaStatics::destructor);
+
+ wantdestruct = true;
}
diff --git a/lib/Handle.cc b/lib/Handle.cc
index 74cf7f4..83eb15d 100644
--- a/lib/Handle.cc
+++ b/lib/Handle.cc
@@ -455,6 +455,14 @@ void Handle::writeU32(Uint32 v) {
#endif
}
+void Handle::copyto(Handle * dest, ssize_t s) {
+ copy(this, dest, s);
+}
+
+void Handle::copyfrom(Handle * src, ssize_t s) {
+ copy(src, this, s);
+}
+
void copyone(Handle * s, Handle * d, ssize_t size) {
long i;
unsigned char c;
diff --git a/lib/LuaHandle.cc b/lib/LuaHandle.cc
new file mode 100644
index 0000000..2a8996e
--- /dev/null
+++ b/lib/LuaHandle.cc
@@ -0,0 +1,463 @@
+#include "LuaHandle.h"
+
+LuaInput::LuaInput(Input * h) : LuaHandle(h) { }
+LuaOutput::LuaOutput(Output * h) : LuaHandle(h) { }
+LuaHandle::LuaHandle(Handle * _h) : h(_h) { }
+
+void LuaInput::pushmembers(Lua * L) {
+ LuaHandle::pushmembers(L);
+}
+
+void LuaOutput::pushmembers(Lua * L) {
+ LuaHandle::pushmembers(L);
+}
+
+class sLuaHandle : public Base {
+ public:
+ static int newinput(lua_State * L);
+ static int newoutput(lua_State * L);
+ static int read(lua_State * L);
+ static int write(lua_State * L);
+ static int readU8(lua_State * L);
+ static int readU16(lua_State * L);
+ static int readU32(lua_State * L);
+ static int writeU8(lua_State * L);
+ static int writeU16(lua_State * L);
+ static int writeU32(lua_State * L);
+ static int copyfrom(lua_State * L);
+ static int copyto(lua_State * L);
+ static int isclosed(lua_State * L);
+ static int isnonblock(lua_State * L);
+ static int canread(lua_State * L);
+ static int canwrite(lua_State * L);
+ static int canseek(lua_State * L);
+ static int canwatch(lua_State * L);
+ static int setnonblock(lua_State * L);
+ static int tell(lua_State * L);
+ static int getname(lua_State * L);
+ static int getsize(lua_State * L);
+ static int getmodif(lua_State * L);
+ static int close(lua_State * L);
+ static int flush(lua_State * L);
+ static int seek(lua_State * L);
+ static int setz(lua_State * L);
+ private:
+ static int read(lua_State * L, int);
+ static int write(lua_State * L, int);
+ static int copy(lua_State * L, int);
+ static int getcaps(lua_State * L, int);
+ static int action(lua_State * L, int);
+ enum {
+ U8, U16, U32
+ };
+ enum {
+ from, to
+ };
+ enum {
+ capisclosed, capisnonblock, capcanread, capcanwrite, capcanseek, capcanwatch
+ };
+ enum {
+ Asetnonblock, Atell, Agetname, Agetsize, Agetmodif, Aclose, Aflush
+ };
+};
+
+void LuaInput::pushconstruct(Lua * L) {
+ L->declarefunc("Input", sLuaHandle::newinput);
+}
+
+void LuaOutput::pushconstruct(Lua * L) {
+ L->declarefunc("Output", sLuaHandle::newoutput);
+}
+
+int sLuaHandle::newinput(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+
+ if ((n != 1) || !L->isstring()) {
+ L->error("Incorrect arguments to constructor `Input'");
+ }
+
+ LuaInput i(new Input(L->tostring()));
+ i.pushdestruct(L);
+
+ return 1;
+}
+
+int sLuaHandle::newoutput(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+
+ if ((n != 1) || !L->isstring()) {
+ L->error("Incorrect arguments to constructor `Input'");
+ }
+
+ LuaOutput o(new Output(L->tostring()));
+ o.pushdestruct(L);
+
+ return 1;
+}
+
+int sLuaHandle::read(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop(), i;
+ size_t t;
+ ssize_t r;
+ Handle * h;
+ Byte * b;
+
+ if ((n != 2) || !L->isnumber()) {
+ L->error("Incorrect arguments to method `Headle::read'");
+ }
+
+ t = L->tonumber();
+ b = (Byte *) malloc(t);
+ h = (Handle *) LuaObject::getme(L);
+
+ L->newtable();
+
+ r = h->read(b, t);
+
+ for (i = 0; i < r; i++) {
+ L->push((lua_Number) i);
+ L->push((lua_Number) b[i]);
+ L->settable();
+ }
+
+ free(b);
+
+ L->push((lua_Number) r);
+
+ return 2;
+}
+
+int sLuaHandle::write(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop(), i;
+ size_t t;
+ ssize_t r;
+ Handle * h;
+ Byte * b;
+
+ if ((n != 3) || !L->isnumber() || !L->istable(2)) {
+ L->error("Incorrect arguments to method `Headle::write'");
+ }
+
+ t = L->tonumber();
+ b = (Byte *) malloc(t);
+ h = (Handle *) LuaObject::getme(L);
+
+ for (i = 0; i < t; i++) {
+ L->push((lua_Number) i);
+ L->gettable(2);
+ b[i] = L->tonumber();
+ L->pop();
+ }
+
+ r = h->write(b, t);
+
+ free(b);
+
+ L->push((lua_Number) r);
+
+ return 1;
+}
+
+int sLuaHandle::readU8(lua_State * L) {
+ return read(L, U8);
+}
+
+int sLuaHandle::readU16(lua_State * L) {
+ return read(L, U16);
+}
+
+int sLuaHandle::readU32(lua_State * L) {
+ return read(L, U32);
+}
+
+int sLuaHandle::writeU8(lua_State * L) {
+ return write(L, U8);
+}
+
+int sLuaHandle::writeU16(lua_State * L) {
+ return write(L, U16);
+}
+
+int sLuaHandle::writeU32(lua_State * L) {
+ return write(L, U32);
+}
+
+int sLuaHandle::read(lua_State * _L, int t) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ lua_Number r;
+ Handle * h;
+
+ if (n != 1) {
+ L->error("Incorrect arguments to method `Headle::readUx'");
+ }
+
+ h = (Handle *) LuaObject::getme(L);
+
+ switch (t) {
+ case U8: r = h->readU8();
+ case U16: r = h->readU16();
+ case U32: r = h->readU32();
+ }
+
+ L->push(r);
+
+ return 1;
+}
+
+int sLuaHandle::write(lua_State * _L, int t) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ lua_Number r;
+ Handle * h;
+
+ if ((n != 2) || !L->isnumber()) {
+ L->error("Incorrect arguments to method `Headle::writeUx'");
+ }
+
+ h = (Handle *) LuaObject::getme(L);
+ r = L->tonumber();
+
+ switch (t) {
+ case U8: h->writeU8(r);
+ case U16: h->writeU16(r);
+ case U32: h->writeU32(r);
+ }
+
+ return 0;
+}
+
+int sLuaHandle::copyfrom(lua_State * L) {
+ return copy(L, from);
+}
+
+int sLuaHandle::copyto(lua_State * L) {
+ return copy(L, to);
+}
+
+int sLuaHandle::copy(lua_State * _L, int dir) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ lua_Number r;
+ Handle * s, * d;
+
+ if ((n < 2) || (n > 3) || ((n == 3) && !L->isnumber(3))) {
+ L->error("Incorrect arguments to function `handlecopy'");
+ }
+
+ s = (Handle *) LuaObject::getme(L, 1);
+ d = (Handle *) LuaObject::getme(L, 2);
+
+ if (n == 3) {
+ r = L->tonumber();
+ } else {
+ r = -1;
+ }
+
+ if (dir == to) {
+ SWAP(s, d);
+ }
+
+ ::copy(s, d, r);
+
+ return 0;
+}
+
+int sLuaHandle::isclosed(lua_State * L) {
+ return getcaps(L, capisclosed);
+}
+
+int sLuaHandle::isnonblock(lua_State * L) {
+ return getcaps(L, capisnonblock);
+}
+
+int sLuaHandle::canread(lua_State * L) {
+ return getcaps(L, capcanread);
+}
+
+int sLuaHandle::canwrite(lua_State * L) {
+ return getcaps(L, capcanwrite);
+}
+
+int sLuaHandle::canseek(lua_State * L) {
+ return getcaps(L, capcanseek);
+}
+
+int sLuaHandle::canwatch(lua_State * L) {
+ return getcaps(L, capcanwatch);
+}
+
+int sLuaHandle::getcaps(lua_State * _L, int cap) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ bool r;
+ Handle * h;
+
+ if (n != 1) {
+ L->error("Incorrect arguments to method `Handle::getcaps'");
+ }
+
+ h = (Handle *) LuaObject::getme(L);
+
+ switch (cap) {
+ case capisclosed: r = h->IsClosed(); break;
+ case capisnonblock: r = h->IsNonBlock(); break;
+ case capcanread: r = h->CanRead(); break;
+ case capcanwrite: r = h->CanWrite(); break;
+ case capcanseek: r = h->CanSeek(); break;
+ case capcanwatch: r = h->CanWatch(); break;
+ }
+
+ L->push(r);
+
+ return 1;
+}
+
+int sLuaHandle::setnonblock(lua_State * L) {
+ return action(L, Asetnonblock);
+}
+
+int sLuaHandle::tell(lua_State * L) {
+ return action(L, Atell);
+}
+
+int sLuaHandle::getname(lua_State * L) {
+ return action(L, Agetname);
+}
+
+int sLuaHandle::getsize(lua_State * L) {
+ return action(L, Agetsize);
+}
+
+int sLuaHandle::getmodif(lua_State * L) {
+ return action(L, Agetmodif);
+}
+
+int sLuaHandle::close(lua_State * L) {
+ return action(L, Aclose);
+}
+
+int sLuaHandle::flush(lua_State * L) {
+ return action(L, Aflush);
+}
+
+int sLuaHandle::action(lua_State * _L, int act) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ int r = 1;
+ Handle * h;
+
+ if (n != 1) {
+ L->error("Incorrect arguments to method `Handle::action'");
+ }
+
+ h = (Handle *) LuaObject::getme(L);
+
+ switch (act) {
+ case Asetnonblock: r = 0; h->SetNonBlock(); break;
+ case Atell: L->push((lua_Number) h->tell()); break;
+ case Agetname: L->push(h->GetName()); break;
+ case Agetsize: L->push((lua_Number) h->GetSize()); break;
+ case Agetmodif: L->push((lua_Number) h->GetModif()); break;
+ case Aclose: r = 0; h->close(); break;
+ case Aflush: r = 0; h->Flush(); break;
+ }
+
+ return r;
+}
+
+int sLuaHandle::seek(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ int z = 9;
+ Handle * h;
+
+ if ((n < 2) || (n > 3) || !L->isnumber(2) || ((n == 3) && !L->isnumber(3))) {
+ L->error("Incorrect arguments to method `Handle::seek'");
+ }
+
+ h = (Handle *) LuaObject::getme(L);
+
+ if (n == 2) {
+ z = L->tonumber(2);
+ }
+
+ h->SetZ(z);
+
+ return 1;
+}
+
+int sLuaHandle::setz(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ off_t off;
+ int wheel = SEEK_SET;
+ Handle * h;
+
+ if ((n < 1) || (n > 2) || ((n == 2) && !L->isnumber(2))) {
+ L->error("Incorrect arguments to method `Handle::setz'");
+ }
+
+ h = (Handle *) LuaObject::getme(L);
+
+ off = L->tonumber(2);
+
+ if (n == 3) {
+ wheel = L->tonumber(3);
+ }
+
+ return 0;
+}
+
+void LuaHandle::pushmembers(Lua * L) {
+ pushme(L, h);
+
+ pushit(L, "read", sLuaHandle::read);
+ pushit(L, "write", sLuaHandle::write);
+
+ pushit(L, "readU8", sLuaHandle::readU8);
+ pushit(L, "readU16", sLuaHandle::readU16);
+ pushit(L, "readU32", sLuaHandle::readU32);
+ pushit(L, "writeU8", sLuaHandle::writeU8);
+ pushit(L, "writeU16", sLuaHandle::writeU16);
+ pushit(L, "writeU32", sLuaHandle::writeU32);
+
+ pushit(L, "copyfrom", sLuaHandle::copyfrom);
+ pushit(L, "copyto", sLuaHandle::copyto);
+ L->declarefunc("handlecopy", sLuaHandle::copyfrom);
+
+ pushit(L, "isclosed", sLuaHandle::isclosed);
+ pushit(L, "isnonblock", sLuaHandle::isnonblock);
+ pushit(L, "canread", sLuaHandle::canread);
+ pushit(L, "canwrite", sLuaHandle::canwatch);
+ pushit(L, "canseek", sLuaHandle::canseek);
+ pushit(L, "canwatch", sLuaHandle::canwatch);
+
+ pushit(L, "setnonblock", sLuaHandle::setnonblock);
+ pushit(L, "tell", sLuaHandle::tell);
+ pushit(L, "getname", sLuaHandle::getname);
+ pushit(L, "getsize", sLuaHandle::getsize);
+ pushit(L, "getmodif", sLuaHandle::getmodif);
+ pushit(L, "close", sLuaHandle::close);
+ pushit(L, "flush", sLuaHandle::flush);
+
+ pushit(L, "seek", sLuaHandle::seek);
+ pushit(L, "setz", sLuaHandle::setz);
+
+ L->push("SEEK_SET");
+ L->push((lua_Number) SEEK_SET);
+ L->settable(LUA_GLOBALSINDEX);
+
+ L->push("SEEK_CUR");
+ L->push((lua_Number) SEEK_CUR);
+ L->settable(LUA_GLOBALSINDEX);
+
+ L->push("SEEK_END");
+ L->push((lua_Number) SEEK_END);
+ L->settable(LUA_GLOBALSINDEX);
+
+}