diff options
Diffstat (limited to 'lib/BLua.cc')
-rw-r--r-- | lib/BLua.cc | 1329 |
1 files changed, 667 insertions, 662 deletions
diff --git a/lib/BLua.cc b/lib/BLua.cc index 1c125a2..9366dd8 100644 --- a/lib/BLua.cc +++ b/lib/BLua.cc @@ -1,662 +1,667 @@ -/* - * Baltisot - * Copyright (C) 1999-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: BLua.cc,v 1.20 2004-07-23 13:08:23 pixel Exp $ */ - -#include "BLua.h" -#include <lualib.h> - -#ifndef BUFFERSIZE -#define BUFFERSIZE 2048 -#endif - - - -extern "C" { - void do_lua_lock(lua_State * _L) { - Lua * L; - try { - L = Lua::find(_L); - } catch (GeneralException e) { - return; - } - L->lock(); - } - - void do_lua_unlock(lua_State * _L) { - Lua * L; - try { - L = Lua::find(_L); - } catch (GeneralException e) { - return; - } - L->unlock(); - } -} - -class LuaStatics : public Base { - public: - static const char * getF(lua_State *, void *, size_t *); - static int putF(lua_State *, const void *, size_t, void *); - static int luapanic(lua_State *); - static int trueluapanic(lua_State *) throw(GeneralException); - static int collector(lua_State *); - static int destructor(lua_State *); - - static int andB(lua_State *); - static int orB(lua_State *); - static int xorB(lua_State *); - static int notB(lua_State *); - static int hex(lua_State *); - static int shl(lua_State *); - static int shr(lua_State *); -}; - -std::map<lua_State *, Lua *> Lua::lualist; - -int LuaStatics::luapanic(lua_State * L) { - return trueluapanic(L); -} - -int LuaStatics::trueluapanic(lua_State * L) throw (GeneralException) { - Lua::find(L)->showerror(); - throw LuaException("Error running Lua code, bailing out."); -} - -int LuaStatics::andB(lua_State * _L) { - Lua * L = Lua::find(_L); - int n = L->gettop(); - Uint32 a, b; - - if ((n != 2) && !L->isnumber(1) && !L->isnumber(2)) { - L->error("Incorrect arguments to function `andB'"); - } - - a = L->tonumber(1); - b = L->tonumber(2); - - L->push((lua_Number) (a & b)); - - return 1; -} - -int LuaStatics::orB(lua_State * _L) { - Lua * L = Lua::find(_L); - int n = L->gettop(); - Uint32 a, b; - - if ((n != 2) && !L->isnumber(1) && !L->isnumber(2)) { - L->error("Incorrect arguments to function `orB'"); - } - - a = L->tonumber(1); - b = L->tonumber(2); - - L->push((lua_Number) (a | b)); - - return 1; -} - -int LuaStatics::xorB(lua_State * _L) { - Lua * L = Lua::find(_L); - int n = L->gettop(); - Uint32 a, b; - - if ((n != 2) && !L->isnumber(1) && !L->isnumber(2)) { - L->error("Incorrect arguments to function `xorB'"); - } - - a = L->tonumber(1); - b = L->tonumber(2); - - L->push((lua_Number) (a ^ b)); - - return 1; -} - -int LuaStatics::notB(lua_State * _L) { - Lua * L = Lua::find(_L); - int n = L->gettop(); - Uint32 x; - - if ((n != 1) && !L->isnumber()) { - L->error("Incorrect arguments to function `notB'"); - } - - x = L->tonumber(); - - L->push((lua_Number) (~x)); - - return 1; -} - -int LuaStatics::shl(lua_State * _L) { - Lua * L = Lua::find(_L); - int n = L->gettop(); - Uint32 a, b; - - if ((n > 2) && !L->isnumber(1) && ((n == 2) && !L->isnumber(2))) { - L->error("Incorrect arguments to function `shl'"); - } - - a = L->tonumber(1); - if (n == 2) - b = L->tonumber(2); - else - b = 1; - - L->push((lua_Number) (a << b)); - - return 1; -} - -int LuaStatics::shr(lua_State * _L) { - Lua * L = Lua::find(_L); - int n = L->gettop(); - Uint32 a, b; - - if ((n > 2) && !L->isnumber(1) && ((n == 2) && !L->isnumber(2))) { - L->error("Incorrect arguments to function `shr'"); - } - - a = L->tonumber(1); - if (n == 2) - b = L->tonumber(2); - else - b = 1; - - L->push((lua_Number) (a >> b)); - - return 1; -} - -int LuaStatics::hex(lua_State * _L) { - Lua * L = Lua::find(_L); - int n = L->gettop(); - int x; - String r; - - if (((n != 1) || (n != 2)) && !L->isnumber(1) && ((n == 2) && !L->isstring(2))) { - L->error("Incorrect arguments to function `hex'"); - } - - x = L->tonumber(1); - String fmt = n == 2 ? L->tostring() : "%02x"; - r.set(fmt.to_charp(), x); - - L->push(r); - - return 1; -} - -Lua::Lua() : L(lua_open()) { - lua_atpanic(L, LuaStatics::luapanic); - lualist[L] = this; - - declarefunc("andB", LuaStatics::andB); - declarefunc("orB", LuaStatics::orB); - declarefunc("xorB", LuaStatics::xorB); - declarefunc("notB", LuaStatics::notB); - declarefunc("shl", LuaStatics::shl); - declarefunc("shr", LuaStatics::shr); - declarefunc("hex", LuaStatics::hex); -} - -Lua::Lua(lua_State * _L) : L(_L) { - lua_atpanic(L, LuaStatics::luapanic); - lualist[L] = this; -} - -Lua::~Lua() { - lua_setgcthreshold(L, 0); - lua_close(L); -} - -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(lua_Number n) { - lua_pushnumber(L, n); -} - -void Lua::push(const String & s) { - lua_pushlstring(L, s.to_charp(), s.strlen()); -} - -void Lua::push(bool b) { - lua_pushboolean(L, b); -} - -void Lua::push(char * s, int size) { - if (size < 0) { - lua_pushstring(L, s); - } else { - lua_pushlstring(L, s, size); - } -} - -void Lua::push(void * p) { - lua_pushlightuserdata(L, p); -} - -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::newuser(size_t s) { - return lua_newuserdata(L, s); -} - -void Lua::settable(int i, bool raw) { - if (raw) { - lua_rawset(L, i); - } else { - lua_settable(L, i); - } -} - -void Lua::gettable(int i, bool raw) { - if (raw) { - lua_rawget(L, i); - } else { - lua_gettable(L, i); - } -} - -void Lua::setvar() { - lua_settable(L, LUA_GLOBALSINDEX); -} - -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 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) { - if (isnil(i)) - return String(); - 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[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, BUFFERSIZE); - return (*size > 0) ? lf->buff : NULL; -} - -struct DumpF { - Handle * f; -}; - -int LuaStatics::putF(lua_State * L, const void * p, size_t size, void * ud) { - DumpF *lf = (DumpF *)ud; - (void)L; - - return lf->f->write(p, size) == size; -} - -void Lua::load(Handle * h, bool docall) throw (GeneralException) { - LoadF lf; - int status; - - lf.f = h; - - status = lua_load(L, LuaStatics::getF, &lf, h->GetName().to_charp()); - - if (status) { - showerror(); - throw LuaException("Error loading lua chunk from Handle `" + h->GetName() + "'"); - } - - if (docall) - call(); -} - -extern "C" void luacmain(lua_State * L, int stripping, lua_Chunkwriter w, void * uD); - -void Lua::dump(Handle * h, bool strip) { - DumpF lf; - - lf.f = h; - - luacmain(L, strip, LuaStatics::putF, &lf); -} - -Lua * Lua::thread() { - return new Lua(lua_newthread(L)); -} - -int Lua::yield(int nargs) { - return lua_yield(L, nargs); -} - -int Lua::resume(int nresults) { - return lua_resume(L, nresults); -} - -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 = String("(Bool) ") + (lua_toboolean(L, i) ? "true" : "false"); - break; - case LUA_TSTRING: - t = String("(String) ") + 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); -} - -int Lua::sethook(lua_Hook func, int mask, int count) { - return lua_sethook(L, func, mask, count); -} - -void Lua::do_break() { - lua_break(L); -} - -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, bool obj) { - void ** u; - bool * b; - L->push("__obj"); - u = (void **) L->newuser(sizeof(o) + sizeof(bool)); - *u = o; - b = (bool *) (u + 1); - *b = obj; - L->settable(-3, true); -} - -void * LuaObject::getme(Lua * L, int i) { - void ** r = 0; - - if (L->istable(i)) { - L->push("__obj"); - L->gettable(i, true); - if (!(r = (void **) L->touserdata())) - L->error("Table is not an object."); - if (!*r) - L->error("Object already destroyed."); - L->pop(); - } else if (L->isnil(i)) { - r = 0; - } else { - L->error("Not an object (not even a table)."); - } - - return r ? *r : 0; -} - -void LuaObject::pushit(Lua * L, const String & s, lua_CFunction f) { - L->push(s); - L->push(f); - L->settable(-3, true); -} - -void LuaObject::pushmeta(Lua * L, const String & s, lua_CFunction f) { - if (!L->getmetatable()) { - L->newtable(); - } - L->push(s); - L->push(f); - L->settable(); - L->setmetatable(); -} - -int LuaStatics::collector(lua_State * _L) { - Lua * L = Lua::find(_L); - void ** u = (void **) L->touserdata(); - bool * obj = (bool *) (u + 1); -// printm(M_INFO, "From LUA: collecting object\n"); - if (*obj) { -// printm(M_INFO, "Is object at %p\n", *u); - Base * b = (Base *) *u; - delete b; - } else { -// printm(M_INFO, "Is struct at %p\n", *u); - free(*u); - } - *u = 0; - return 0; -} - -int LuaStatics::destructor(lua_State * _L) { - Lua * L = Lua::find(_L); - Base * b = (Base *) LuaObject::getme(L); - delete b; - L->push("__obj"); - L->gettable(-2, true); - void ** u = (void **) L->touserdata(); - bool * obj = (bool *) (u + 1); - if (*obj) { - Base * b = (Base *) *u; - delete b; - } else { - free(*u); - } - *u = 0; - L->pop(); - return 0; -} - -void LuaObject::pushdestruct(Lua * L) throw (GeneralException) { - if (pushed) { - throw GeneralException("Error: can't push destructor, object already pushed"); - } - push(L); - L->push("__obj"); - L->gettable(-2, true); - pushmeta(L, "__gc", LuaStatics::collector); - L->pop(); - pushit(L, "destroy", LuaStatics::destructor); - - wantdestruct = true; -} - -LuaException::LuaException(String fn) : GeneralException(fn) { } - -LuaException::LuaException() { } +/*
+ * Baltisot
+ * Copyright (C) 1999-2003 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* $Id: BLua.cc,v 1.21 2004-11-27 21:01:20 pixel Exp $ */
+
+#include "BLua.h"
+#include <lualib.h>
+
+#ifndef BUFFERSIZE
+#define BUFFERSIZE 2048
+#endif
+
+
+
+extern "C" {
+ void do_lua_lock(lua_State * _L) {
+ Lua * L;
+ try {
+ L = Lua::find(_L);
+ } catch (GeneralException e) {
+ return;
+ }
+ L->lock();
+ }
+
+ void do_lua_unlock(lua_State * _L) {
+ Lua * L;
+ try {
+ L = Lua::find(_L);
+ } catch (GeneralException e) {
+ return;
+ }
+ L->unlock();
+ }
+}
+
+class LuaStatics : public Base {
+ public:
+ static const char * getF(lua_State *, void *, size_t *);
+ static int putF(lua_State *, const void *, size_t, void *);
+ static int luapanic(lua_State *);
+ static int trueluapanic(lua_State *) throw(GeneralException);
+ static int collector(lua_State *);
+ static int destructor(lua_State *);
+
+ static int andB(lua_State *);
+ static int orB(lua_State *);
+ static int xorB(lua_State *);
+ static int notB(lua_State *);
+ static int hex(lua_State *);
+ static int shl(lua_State *);
+ static int shr(lua_State *);
+};
+
+std::map<lua_State *, Lua *> Lua::lualist;
+
+int LuaStatics::luapanic(lua_State * L) {
+ return trueluapanic(L);
+}
+
+int LuaStatics::trueluapanic(lua_State * L) throw (GeneralException) {
+ Lua::find(L)->showerror();
+ throw LuaException("Error running Lua code, bailing out.");
+}
+
+int LuaStatics::andB(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ Uint32 a, b;
+
+ if ((n != 2) && !L->isnumber(1) && !L->isnumber(2)) {
+ L->error("Incorrect arguments to function `andB'");
+ }
+
+ a = L->tonumber(1);
+ b = L->tonumber(2);
+
+ L->push((lua_Number) (a & b));
+
+ return 1;
+}
+
+int LuaStatics::orB(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ Uint32 a, b;
+
+ if ((n != 2) && !L->isnumber(1) && !L->isnumber(2)) {
+ L->error("Incorrect arguments to function `orB'");
+ }
+
+ a = L->tonumber(1);
+ b = L->tonumber(2);
+
+ L->push((lua_Number) (a | b));
+
+ return 1;
+}
+
+int LuaStatics::xorB(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ Uint32 a, b;
+
+ if ((n != 2) && !L->isnumber(1) && !L->isnumber(2)) {
+ L->error("Incorrect arguments to function `xorB'");
+ }
+
+ a = L->tonumber(1);
+ b = L->tonumber(2);
+
+ L->push((lua_Number) (a ^ b));
+
+ return 1;
+}
+
+int LuaStatics::notB(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ Uint32 x;
+
+ if ((n != 1) && !L->isnumber()) {
+ L->error("Incorrect arguments to function `notB'");
+ }
+
+ x = L->tonumber();
+
+ L->push((lua_Number) (~x));
+
+ return 1;
+}
+
+int LuaStatics::shl(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ Uint32 a, b;
+
+ if ((n > 2) && !L->isnumber(1) && ((n == 2) && !L->isnumber(2))) {
+ L->error("Incorrect arguments to function `shl'");
+ }
+
+ a = L->tonumber(1);
+ if (n == 2)
+ b = L->tonumber(2);
+ else
+ b = 1;
+
+ L->push((lua_Number) (a << b));
+
+ return 1;
+}
+
+int LuaStatics::shr(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ Uint32 a, b;
+
+ if ((n > 2) && !L->isnumber(1) && ((n == 2) && !L->isnumber(2))) {
+ L->error("Incorrect arguments to function `shr'");
+ }
+
+ a = L->tonumber(1);
+ if (n == 2)
+ b = L->tonumber(2);
+ else
+ b = 1;
+
+ L->push((lua_Number) (a >> b));
+
+ return 1;
+}
+
+int LuaStatics::hex(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ int n = L->gettop();
+ int x;
+ String r;
+
+ if (((n != 1) || (n != 2)) && !L->isnumber(1) && ((n == 2) && !L->isstring(2))) {
+ L->error("Incorrect arguments to function `hex'");
+ }
+
+ x = L->tonumber(1);
+ String fmt = n == 2 ? L->tostring() : "%02x";
+ r.set(fmt.to_charp(), x);
+
+ L->push(r);
+
+ return 1;
+}
+
+Lua::Lua() : L(lua_open()) {
+ lua_atpanic(L, LuaStatics::luapanic);
+ lualist[L] = this;
+
+ declarefunc("andB", LuaStatics::andB);
+ declarefunc("orB", LuaStatics::orB);
+ declarefunc("xorB", LuaStatics::xorB);
+ declarefunc("notB", LuaStatics::notB);
+ declarefunc("shl", LuaStatics::shl);
+ declarefunc("shr", LuaStatics::shr);
+ declarefunc("hex", LuaStatics::hex);
+}
+
+Lua::Lua(lua_State * _L) : L(_L) {
+ lua_atpanic(L, LuaStatics::luapanic);
+ lualist[L] = this;
+}
+
+Lua::~Lua() {
+ lua_setgcthreshold(L, 0);
+ lua_close(L);
+}
+
+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::open_dir() {
+ luaopen_dir(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(lua_Number n) {
+ lua_pushnumber(L, n);
+}
+
+void Lua::push(const String & s) {
+ lua_pushlstring(L, s.to_charp(), s.strlen());
+}
+
+void Lua::push(bool b) {
+ lua_pushboolean(L, b);
+}
+
+void Lua::push(char * s, int size) {
+ if (size < 0) {
+ lua_pushstring(L, s);
+ } else {
+ lua_pushlstring(L, s, size);
+ }
+}
+
+void Lua::push(void * p) {
+ lua_pushlightuserdata(L, p);
+}
+
+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::newuser(size_t s) {
+ return lua_newuserdata(L, s);
+}
+
+void Lua::settable(int i, bool raw) {
+ if (raw) {
+ lua_rawset(L, i);
+ } else {
+ lua_settable(L, i);
+ }
+}
+
+void Lua::gettable(int i, bool raw) {
+ if (raw) {
+ lua_rawget(L, i);
+ } else {
+ lua_gettable(L, i);
+ }
+}
+
+void Lua::setvar() {
+ lua_settable(L, LUA_GLOBALSINDEX);
+}
+
+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 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) {
+ if (isnil(i))
+ return String();
+ 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[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, BUFFERSIZE);
+ return (*size > 0) ? lf->buff : NULL;
+}
+
+struct DumpF {
+ Handle * f;
+};
+
+int LuaStatics::putF(lua_State * L, const void * p, size_t size, void * ud) {
+ DumpF *lf = (DumpF *)ud;
+ (void)L;
+
+ return lf->f->write(p, size) == size;
+}
+
+void Lua::load(Handle * h, bool docall) throw (GeneralException) {
+ LoadF lf;
+ int status;
+
+ lf.f = h;
+
+ status = lua_load(L, LuaStatics::getF, &lf, h->GetName().to_charp());
+
+ if (status) {
+ showerror();
+ throw LuaException("Error loading lua chunk from Handle `" + h->GetName() + "'");
+ }
+
+ if (docall)
+ call();
+}
+
+extern "C" void luacmain(lua_State * L, int stripping, lua_Chunkwriter w, void * uD);
+
+void Lua::dump(Handle * h, bool strip) {
+ DumpF lf;
+
+ lf.f = h;
+
+ luacmain(L, strip, LuaStatics::putF, &lf);
+}
+
+Lua * Lua::thread() {
+ return new Lua(lua_newthread(L));
+}
+
+int Lua::yield(int nargs) {
+ return lua_yield(L, nargs);
+}
+
+int Lua::resume(int nresults) {
+ return lua_resume(L, nresults);
+}
+
+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 = String("(Bool) ") + (lua_toboolean(L, i) ? "true" : "false");
+ break;
+ case LUA_TSTRING:
+ t = String("(String) ") + 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);
+}
+
+int Lua::sethook(lua_Hook func, int mask, int count) {
+ return lua_sethook(L, func, mask, count);
+}
+
+void Lua::do_break() {
+ lua_break(L);
+}
+
+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, bool obj) {
+ void ** u;
+ bool * b;
+ L->push("__obj");
+ u = (void **) L->newuser(sizeof(o) + sizeof(bool));
+ *u = o;
+ b = (bool *) (u + 1);
+ *b = obj;
+ L->settable(-3, true);
+}
+
+void * LuaObject::getme(Lua * L, int i) {
+ void ** r = 0;
+
+ if (L->istable(i)) {
+ L->push("__obj");
+ L->gettable(i, true);
+ if (!(r = (void **) L->touserdata()))
+ L->error("Table is not an object.");
+ if (!*r)
+ L->error("Object already destroyed.");
+ L->pop();
+ } else if (L->isnil(i)) {
+ r = 0;
+ } else {
+ L->error("Not an object (not even a table).");
+ }
+
+ return r ? *r : 0;
+}
+
+void LuaObject::pushit(Lua * L, const String & s, lua_CFunction f) {
+ L->push(s);
+ L->push(f);
+ L->settable(-3, true);
+}
+
+void LuaObject::pushmeta(Lua * L, const String & s, lua_CFunction f) {
+ if (!L->getmetatable()) {
+ L->newtable();
+ }
+ L->push(s);
+ L->push(f);
+ L->settable();
+ L->setmetatable();
+}
+
+int LuaStatics::collector(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ void ** u = (void **) L->touserdata();
+ bool * obj = (bool *) (u + 1);
+// printm(M_INFO, "From LUA: collecting object\n");
+ if (*obj) {
+// printm(M_INFO, "Is object at %p\n", *u);
+ Base * b = (Base *) *u;
+ delete b;
+ } else {
+// printm(M_INFO, "Is struct at %p\n", *u);
+ free(*u);
+ }
+ *u = 0;
+ return 0;
+}
+
+int LuaStatics::destructor(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ Base * b = (Base *) LuaObject::getme(L);
+ delete b;
+ L->push("__obj");
+ L->gettable(-2, true);
+ void ** u = (void **) L->touserdata();
+ bool * obj = (bool *) (u + 1);
+ if (*obj) {
+ Base * b = (Base *) *u;
+ delete b;
+ } else {
+ free(*u);
+ }
+ *u = 0;
+ L->pop();
+ return 0;
+}
+
+void LuaObject::pushdestruct(Lua * L) throw (GeneralException) {
+ if (pushed) {
+ throw GeneralException("Error: can't push destructor, object already pushed");
+ }
+ push(L);
+ L->push("__obj");
+ L->gettable(-2, true);
+ pushmeta(L, "__gc", LuaStatics::collector);
+ L->pop();
+ pushit(L, "destroy", LuaStatics::destructor);
+
+ wantdestruct = true;
+}
+
+LuaException::LuaException(String fn) : GeneralException(fn) { }
+
+LuaException::LuaException() { }
|