Tizen 2.1 base
authorJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:45:19 +0000 (01:45 +0900)
committerJinkun Jang <jinkun.jang@samsung.com>
Tue, 12 Mar 2013 16:45:19 +0000 (01:45 +0900)
13 files changed:
CMakeLists.txt [new file with mode: 0755]
COPYRIGHT [new file with mode: 0644]
README [new file with mode: 0644]
README-5.1 [new file with mode: 0755]
packaging/tolua++.spec [new file with mode: 0755]
tolua++.h [new file with mode: 0644]
tolua.manifest [new file with mode: 0644]
tolua_event.c [new file with mode: 0644]
tolua_event.h [new file with mode: 0644]
tolua_is.c [new file with mode: 0644]
tolua_map.c [new file with mode: 0644]
tolua_push.c [new file with mode: 0644]
tolua_to.c [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..20e7e16
--- /dev/null
@@ -0,0 +1,32 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+PROJECT(tolua++)
+
+INCLUDE_DIRECTORIES(
+       /usr/include/
+)
+
+set(MODULE_DIR ${CMAKE_SOURCE_DIR})
+
+SET (${PROJECT_NAME}_SOURCE_FILES
+       ${MODULE_DIR}/tolua_event.c
+       ${MODULE_DIR}/tolua_to.c
+       ${MODULE_DIR}/tolua_is.c
+       ${MODULE_DIR}/tolua_push.c
+       ${MODULE_DIR}/tolua_map.c
+)
+
+LIST (APPEND SRCS ${${PROJECT_NAME}_SOURCE_FILES})
+
+INCLUDE_DIRECTORIES(
+       ${MODULE_DIR}
+) 
+
+add_library(${PROJECT_NAME} STATIC ${SRCS})
+
+SET(CMAKE_C_FLAGS "-fPIC ${OSP_DEBUG_FLAGS} ${OSP_OPT_FLAGS} ${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ${OSP_COMPILER_FLAGS}")
+SET(CMAKE_CXX_FLAGS "-fPIC ${OSP_DEBUG_FLAGS} ${OSP_OPT_FLAGS} ${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} ${OSP_COMPILER_FLAGS}")
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/tolua++.h DESTINATION include/)
+
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644 (file)
index 0000000..9e99e00
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,33 @@
+tolua++ License
+---------------
+
+tolua++ is based on toLua (www.tecgraf.puc-rio.br/~celes/tolua), and
+it's licensed under the terms of the MIT license reproduced below.
+This means that Lua is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+
+===============================================================================
+
+Copyright (C) 2009 Ariel Manzur.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+===============================================================================
+
+(end of COPYRIGHT)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..cee381f
--- /dev/null
+++ b/README
@@ -0,0 +1,30 @@
+This is tolua++-1.0
+
+* What is tolua++?
+  tolua++ is an extension of toLua, a tool to integrate C/C++ code with
+  Lua. tolua++ includes new features oriented to c++, such as class
+  templates.
+
+  tolua is a tool that greatly simplifies the integration of C/C++ code 
+  with Lua. Based on a "cleaned" header file, tolua automatically generates 
+  the binding code to access C/C++ features from Lua. Using Lua-5.0 API and
+  metamethod facilities, the current version automatically maps C/C++ 
+  constants, external variables, functions, namespace, classes, and methods 
+  to Lua. It also provides facilities to create Lua modules.
+
+* Availability
+
+  tolua++ is freely available for both academic and commercial purposes.
+  See COPYRIGHT for details.
+
+  tolua++ can be downloaded from the sites below:
+            http://www.codenix.com/~tolua/
+
+* Installation
+  See INSTALL.
+
+* Contacting the author
+  tolua has been designed and implemented by Waldemar Celes.
+  tolua++ is maintained by Ariel Manzur.
+  Send your comments, bug reports and anything else to 
+  tolua@codenix.com
diff --git a/README-5.1 b/README-5.1
new file mode 100755 (executable)
index 0000000..f06f785
--- /dev/null
@@ -0,0 +1,50 @@
+Compiling for lua 5.1
+---------------------
+
+Starting from version 1.0.8pre1, tolua++ can be compiled with both lua 5.0 and
+5.1. Both versions will output the same code, and the C API (tolua++.h) is the
+same.
+
+The build system is not yet ready to detect/decide when to compile for 5.1,
+the easiest way right now is to add a file called 'custom.py' on the root of
+the package, with the following:
+
+## BEGIN custom.py
+
+CCFLAGS = ['-I/usr/local/include/lua5.1', '-O2', '-ansi']
+LIBPATH = ['/usr/local/lib']
+LIBS = ['lua5.1', 'dl', 'm']
+tolua_bin = 'tolua++5.1'
+tolua_lib = 'tolua++5.1'
+TOLUAPP = 'tolua++5.1'
+
+## END custom.py
+
+This will build the binary as 'tolua++5.1' and the library as 'libtolua++5.1.a'
+(taken from tolua_bin and tolua_lib), and take the lua headers and libraries
+from /usr/local/include/lua5.1 and /usr/local/lib. It will also link with
+'-llua5.1'. Modify the parameters acording to your system.
+
+Compatibility
+-------------
+
+There are a couple of things to keep in mind when running code inside tolua
+using the -L option:
+
+* `...' and arg: you can still use 'arg' on 5.1, this is done automatically by
+adding the 'arg' declaration to functions on files loaded with dofile.
+
+For example, the line:
+
+function foo( ... )
+
+becomes
+
+function foo( ... ) local arg = {n=select('#', ...), ...};
+
+This lets you use the same code on both versions without having to make any
+modifications.
+
+* keep in mind that there are slight differences on the way string.gsub works,
+and the original version of the function is always kept, so it will behave
+diffently depending on which version of lua you're using.
diff --git a/packaging/tolua++.spec b/packaging/tolua++.spec
new file mode 100755 (executable)
index 0000000..42a94d0
--- /dev/null
@@ -0,0 +1,58 @@
+Name:       tolua++
+Summary:    tolua++ package
+Version:    1.0.93
+Release:    1
+Group:      TO_BE/FILLED_IN
+License:    TO BE FILLED IN
+Source0:    %{name}-%{version}.tar.gz
+BuildRequires:  liblua-devel
+BuildRequires:  cmake
+
+%description
+tolua++ package
+
+%package devel
+Summary:    tolua++ package (devel)
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+tolua++ package (devel)
+
+%prep
+%setup -q
+
+%build
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+%ifarch %{ix86}
+CXXFLAGS="$CXXFLAGS -D_OSP_DEBUG_ -D_OSP_X86_ -D_OSP_EMUL_" cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DOBS=1 -DFULLVER=%{version} -DMAJORVER=${MAJORVER} -DARCH=x86
+%else
+CXXFLAGS="$CXXFLAGS -mthumb -Wa,-mimplicit-it=thumb -D_OSP_DEBUG_ -D_OSP_ARMEL_" cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DOBS=1 -DFULLVER=%{version} -DMAJORVER=${MAJORVER} -DARCH=arm
+%endif
+
+
+# Call make instruction with smp support
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp %{_builddir}/%{name}-%{version}/COPYRIGHT  %{buildroot}/usr/share/license/%{name}
+
+%{__make} DESTDIR=%{?buildroot:%{buildroot}} INSTALL_ROOT=%{?buildroot:%{buildroot}} install
+rm -f %{?buildroot:%{buildroot}}%{_infodir}/dir
+find %{?buildroot:%{buildroot}} -regex ".*\\.la$" | xargs rm -f --
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%manifest tolua.manifest
+%defattr(-,root,root,-)
+/usr/share/license/%{name}
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/tolua++.h
+%{_libdir}/libtolua++.a
diff --git a/tolua++.h b/tolua++.h
new file mode 100644 (file)
index 0000000..ed53449
--- /dev/null
+++ b/tolua++.h
@@ -0,0 +1,186 @@
+/* tolua
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+
+#ifndef TOLUA_H
+#define TOLUA_H
+
+#ifndef TOLUA_API
+#define TOLUA_API extern
+#endif
+
+#define TOLUA_VERSION "tolua++-1.0.92"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define tolua_pushcppstring(x,y)       tolua_pushstring(x,y.c_str())
+#define tolua_iscppstring      tolua_isstring
+
+#define tolua_iscppstringarray tolua_isstringarray
+#define tolua_pushfieldcppstring(L,lo,idx,s) tolua_pushfieldstring(L, lo, idx, s.c_str())
+
+#ifndef TEMPLATE_BIND
+ #define TEMPLATE_BIND(p)
+#endif
+
+#define TOLUA_TEMPLATE_BIND(p)
+
+#define TOLUA_PROTECTED_DESTRUCTOR
+#define TOLUA_PROPERTY_TYPE(p)
+
+typedef int lua_Object;
+
+#include "lua.h"
+#include "lauxlib.h"
+
+struct tolua_Error
+{
+       int index;
+       int array;
+       const char* type;
+};
+typedef struct tolua_Error tolua_Error;
+
+#define TOLUA_NOPEER   LUA_REGISTRYINDEX /* for lua 5.1 */
+
+TOLUA_API const char* tolua_typename (lua_State* L, int lo);
+TOLUA_API void tolua_error (lua_State* L, const char* msg, tolua_Error* err);
+TOLUA_API int tolua_isnoobj (lua_State* L, int lo, tolua_Error* err);
+TOLUA_API int tolua_isvalue (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isvaluenil (lua_State* L, int lo, tolua_Error* err);
+TOLUA_API int tolua_isboolean (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isnumber (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isstring (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_istable (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isusertable (lua_State* L, int lo, const char* type, int def, tolua_Error* err);
+TOLUA_API int tolua_isuserdata (lua_State* L, int lo, int def, tolua_Error* err);
+TOLUA_API int tolua_isusertype (lua_State* L, int lo, const char* type, int def, tolua_Error* err);
+TOLUA_API int tolua_isvaluearray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isbooleanarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isnumberarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isstringarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_istablearray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isuserdataarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err);
+TOLUA_API int tolua_isusertypearray
+ (lua_State* L, int lo, const char* type, int dim, int def, tolua_Error* err);
+
+TOLUA_API void tolua_open (lua_State* L);
+
+TOLUA_API void* tolua_copy (lua_State* L, void* value, unsigned int size);
+TOLUA_API int tolua_register_gc (lua_State* L, int lo);
+TOLUA_API int tolua_default_collect (lua_State* tolua_S);
+
+TOLUA_API void tolua_usertype (lua_State* L, const char* type);
+TOLUA_API void tolua_beginmodule (lua_State* L, const char* name);
+TOLUA_API void tolua_endmodule (lua_State* L);
+TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar);
+TOLUA_API void tolua_class (lua_State* L, const char* name, const char* base);
+TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col);
+TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func);
+TOLUA_API void tolua_constant (lua_State* L, const char* name, lua_Number value);
+TOLUA_API void tolua_variable (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set);
+TOLUA_API void tolua_array (lua_State* L,const char* name, lua_CFunction get, lua_CFunction set);
+
+/* TOLUA_API void tolua_set_call_event(lua_State* L, lua_CFunction func, char* type); */
+/* TOLUA_API void tolua_addbase(lua_State* L, char* name, char* base); */
+
+TOLUA_API void tolua_pushvalue (lua_State* L, int lo);
+TOLUA_API void tolua_pushboolean (lua_State* L, int value);
+TOLUA_API void tolua_pushnumber (lua_State* L, lua_Number value);
+TOLUA_API void tolua_pushstring (lua_State* L, const char* value);
+TOLUA_API void tolua_pushuserdata (lua_State* L, void* value);
+TOLUA_API void tolua_pushusertype (lua_State* L, void* value, const char* type);
+TOLUA_API void tolua_pushusertype_and_takeownership(lua_State* L, void* value, const char* type);
+TOLUA_API void tolua_pushfieldvalue (lua_State* L, int lo, int index, int v);
+TOLUA_API void tolua_pushfieldboolean (lua_State* L, int lo, int index, int v);
+TOLUA_API void tolua_pushfieldnumber (lua_State* L, int lo, int index, lua_Number v);
+TOLUA_API void tolua_pushfieldstring (lua_State* L, int lo, int index, const char* v);
+TOLUA_API void tolua_pushfielduserdata (lua_State* L, int lo, int index, void* v);
+TOLUA_API void tolua_pushfieldusertype (lua_State* L, int lo, int index, void* v, const char* type);
+TOLUA_API void tolua_pushfieldusertype_and_takeownership (lua_State* L, int lo, int index, void* v, const char* type);
+
+TOLUA_API lua_Number tolua_tonumber (lua_State* L, int narg, lua_Number def);
+TOLUA_API const char* tolua_tostring (lua_State* L, int narg, const char* def);
+TOLUA_API void* tolua_touserdata (lua_State* L, int narg, void* def);
+TOLUA_API void* tolua_tousertype (lua_State* L, int narg, void* def);
+TOLUA_API int tolua_tovalue (lua_State* L, int narg, int def);
+TOLUA_API int tolua_toboolean (lua_State* L, int narg, int def);
+TOLUA_API lua_Number tolua_tofieldnumber (lua_State* L, int lo, int index, lua_Number def);
+TOLUA_API const char* tolua_tofieldstring (lua_State* L, int lo, int index, const char* def);
+TOLUA_API void* tolua_tofielduserdata (lua_State* L, int lo, int index, void* def);
+TOLUA_API void* tolua_tofieldusertype (lua_State* L, int lo, int index, void* def);
+TOLUA_API int tolua_tofieldvalue (lua_State* L, int lo, int index, int def);
+TOLUA_API int tolua_getfieldboolean (lua_State* L, int lo, int index, int def);
+
+TOLUA_API void tolua_dobuffer(lua_State* L, char* B, unsigned int size, const char* name);
+
+TOLUA_API int class_gc_event (lua_State* L);
+
+#ifdef __cplusplus
+static inline const char* tolua_tocppstring (lua_State* L, int narg, const char* def) {
+
+       const char* s = tolua_tostring(L, narg, def);
+       return s?s:"";
+};
+
+static inline const char* tolua_tofieldcppstring (lua_State* L, int lo, int index, const char* def) {
+
+       const char* s = tolua_tofieldstring(L, lo, index, def);
+       return s?s:"";
+};
+
+#else
+#define tolua_tocppstring tolua_tostring
+#define tolua_tofieldcppstring tolua_tofieldstring
+#endif
+
+TOLUA_API int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int super_index);
+
+#ifndef Mtolua_new
+#define Mtolua_new(EXP) new EXP
+#endif
+
+#ifndef Mtolua_delete
+#define Mtolua_delete(EXP) delete EXP
+#endif
+
+#ifndef Mtolua_new_dim
+#define Mtolua_new_dim(EXP, len) new EXP[len]
+#endif
+
+#ifndef Mtolua_delete_dim
+#define Mtolua_delete_dim(EXP) delete [] EXP
+#endif
+
+#ifndef tolua_outside
+#define tolua_outside
+#endif
+
+#ifndef tolua_owned
+#define tolua_owned
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tolua.manifest b/tolua.manifest
new file mode 100644 (file)
index 0000000..ae3e6f7
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
\ No newline at end of file
diff --git a/tolua_event.c b/tolua_event.c
new file mode 100644 (file)
index 0000000..8258867
--- /dev/null
@@ -0,0 +1,536 @@
+/* tolua: event functions
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include <stdio.h>
+
+#include "tolua++.h"
+
+/* Store at ubox
+       * It stores, creating the corresponding table if needed,
+       * the pair key/value in the corresponding ubox table
+*/
+static void storeatubox (lua_State* L, int lo)
+{
+       #ifdef LUA_VERSION_NUM
+               lua_getfenv(L, lo);
+               if (lua_rawequal(L, -1, TOLUA_NOPEER)) {
+                       lua_pop(L, 1);
+                       lua_newtable(L);
+                       lua_pushvalue(L, -1);
+                       lua_setfenv(L, lo);     /* stack: k,v,table  */
+               };
+               lua_insert(L, -3);
+               lua_settable(L, -3); /* on lua 5.1, we trade the "tolua_peers" lookup for a settable call */
+               lua_pop(L, 1);
+       #else
+        /* stack: key value (to be stored) */
+               lua_pushstring(L,"tolua_peers");
+               lua_rawget(L,LUA_REGISTRYINDEX);        /* stack: k v ubox */
+               lua_pushvalue(L,lo);
+               lua_rawget(L,-2);                       /* stack: k v ubox ubox[u] */
+               if (!lua_istable(L,-1))
+               {
+                       lua_pop(L,1);                          /* stack: k v ubox */
+                       lua_newtable(L);                       /* stack: k v ubox table */
+                       lua_pushvalue(L,1);
+                       lua_pushvalue(L,-2);                   /* stack: k v ubox table u table */
+                       lua_rawset(L,-4);                      /* stack: k v ubox ubox[u]=table */
+               }
+               lua_insert(L,-4);                       /* put table before k */
+               lua_pop(L,1);                           /* pop ubox */
+               lua_rawset(L,-3);                       /* store at table */
+               lua_pop(L,1);                           /* pop ubox[u] */
+       #endif
+}
+
+/* Module index function
+*/
+static int module_index_event (lua_State* L)
+{
+       lua_pushstring(L,".get");
+       lua_rawget(L,-3);
+       if (lua_istable(L,-1))
+       {
+               lua_pushvalue(L,2);  /* key */
+               lua_rawget(L,-2);
+               if (lua_iscfunction(L,-1))
+               {
+                       lua_call(L,0,1);
+                       return 1;
+               }
+               else if (lua_istable(L,-1))
+                       return 1;
+       }
+       /* call old index meta event */
+       if (lua_getmetatable(L,1))
+       {
+               lua_pushstring(L,"__index");
+               lua_rawget(L,-2);
+               lua_pushvalue(L,1);
+               lua_pushvalue(L,2);
+               if (lua_isfunction(L,-1))
+               {
+                       lua_call(L,2,1);
+                       return 1;
+               }
+               else if (lua_istable(L,-1))
+               {
+                       lua_gettable(L,-3);
+                       return 1;
+               }
+       }
+       lua_pushnil(L);
+       return 1;
+}
+
+/* Module newindex function
+*/
+static int module_newindex_event (lua_State* L)
+{
+       lua_pushstring(L,".set");
+       lua_rawget(L,-4);
+       if (lua_istable(L,-1))
+       {
+               lua_pushvalue(L,2);  /* key */
+               lua_rawget(L,-2);
+               if (lua_iscfunction(L,-1))
+               {
+                       lua_pushvalue(L,1); /* only to be compatible with non-static vars */
+                       lua_pushvalue(L,3); /* value */
+                       lua_call(L,2,0);
+                       return 0;
+               }
+       }
+       /* call old newindex meta event */
+       if (lua_getmetatable(L,1) && lua_getmetatable(L,-1))
+       {
+               lua_pushstring(L,"__newindex");
+               lua_rawget(L,-2);
+               if (lua_isfunction(L,-1))
+               {
+                lua_pushvalue(L,1);
+                lua_pushvalue(L,2);
+                lua_pushvalue(L,3);
+                       lua_call(L,3,0);
+               }
+       }
+       lua_settop(L,3);
+       lua_rawset(L,-3);
+       return 0;
+}
+
+/* Class index function
+       * If the object is a userdata (ie, an object), it searches the field in
+       * the alternative table stored in the corresponding "ubox" table.
+*/
+static int class_index_event (lua_State* L)
+{
+ int t = lua_type(L,1);
+       if (t == LUA_TUSERDATA)
+       {
+               /* Access alternative table */
+               #ifdef LUA_VERSION_NUM /* new macro on version 5.1 */
+               lua_getfenv(L,1);
+               if (!lua_rawequal(L, -1, TOLUA_NOPEER)) {
+                       lua_pushvalue(L, 2); /* key */
+                       lua_gettable(L, -2); /* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */
+                       if (!lua_isnil(L, -1))
+                               return 1;
+               };
+               #else
+               lua_pushstring(L,"tolua_peers");
+               lua_rawget(L,LUA_REGISTRYINDEX);        /* stack: obj key ubox */
+               lua_pushvalue(L,1);
+               lua_rawget(L,-2);                       /* stack: obj key ubox ubox[u] */
+               if (lua_istable(L,-1))
+               {
+                       lua_pushvalue(L,2);  /* key */
+                       lua_rawget(L,-2);                      /* stack: obj key ubox ubox[u] value */
+                       if (!lua_isnil(L,-1))
+                               return 1;
+               }
+               #endif
+               lua_settop(L,2);                        /* stack: obj key */
+               /* Try metatables */
+               lua_pushvalue(L,1);                     /* stack: obj key obj */
+               while (lua_getmetatable(L,-1))
+               {                                       /* stack: obj key obj mt */
+                       lua_remove(L,-2);                      /* stack: obj key mt */
+                       if (lua_isnumber(L,2))                 /* check if key is a numeric value */
+                       {
+                               /* try operator[] */
+                               lua_pushstring(L,".geti");
+                               lua_rawget(L,-2);                      /* stack: obj key mt func */
+                               if (lua_isfunction(L,-1))
+                               {
+                                       lua_pushvalue(L,1);
+                                       lua_pushvalue(L,2);
+                                       lua_call(L,2,1);
+                                       return 1;
+                               }
+                       }
+                       else
+                       {
+                        lua_pushvalue(L,2);                    /* stack: obj key mt key */
+                               lua_rawget(L,-2);                      /* stack: obj key mt value */
+                               if (!lua_isnil(L,-1))
+                                       return 1;
+                               else
+                                       lua_pop(L,1);
+                               /* try C/C++ variable */
+                               lua_pushstring(L,".get");
+                               lua_rawget(L,-2);                      /* stack: obj key mt tget */
+                               if (lua_istable(L,-1))
+                               {
+                                       lua_pushvalue(L,2);
+                                       lua_rawget(L,-2);                      /* stack: obj key mt value */
+                                       if (lua_iscfunction(L,-1))
+                                       {
+                                               lua_pushvalue(L,1);
+                                               lua_pushvalue(L,2);
+                                               lua_call(L,2,1);
+                                               return 1;
+                                       }
+                                       else if (lua_istable(L,-1))
+                                       {
+                                               /* deal with array: create table to be returned and cache it in ubox */
+                                               void* u = *((void**)lua_touserdata(L,1));
+                                               lua_newtable(L);                /* stack: obj key mt value table */
+                                               lua_pushstring(L,".self");
+                                               lua_pushlightuserdata(L,u);
+                                               lua_rawset(L,-3);               /* store usertype in ".self" */
+                                               lua_insert(L,-2);               /* stack: obj key mt table value */
+                                               lua_setmetatable(L,-2);         /* set stored value as metatable */
+                                               lua_pushvalue(L,-1);            /* stack: obj key met table table */
+                                               lua_pushvalue(L,2);             /* stack: obj key mt table table key */
+                                               lua_insert(L,-2);               /*  stack: obj key mt table key table */
+                                               storeatubox(L,1);               /* stack: obj key mt table */
+                                               return 1;
+                                       }
+                               }
+                       }
+                       lua_settop(L,3);
+               }
+               lua_pushnil(L);
+               return 1;
+       }
+       else if (t== LUA_TTABLE)
+       {
+               module_index_event(L);
+               return 1;
+       }
+       lua_pushnil(L);
+       return 1;
+}
+
+/* Newindex function
+       * It first searches for a C/C++ varaible to be set.
+       * Then, it either stores it in the alternative ubox table (in the case it is
+       * an object) or in the own table (that represents the class or module).
+*/
+static int class_newindex_event (lua_State* L)
+{
+ int t = lua_type(L,1);
+       if (t == LUA_TUSERDATA)
+       {
+        /* Try accessing a C/C++ variable to be set */
+               lua_getmetatable(L,1);
+               while (lua_istable(L,-1))                /* stack: t k v mt */
+               {
+                       if (lua_isnumber(L,2))                 /* check if key is a numeric value */
+                       {
+                               /* try operator[] */
+                               lua_pushstring(L,".seti");
+                               lua_rawget(L,-2);                      /* stack: obj key mt func */
+                               if (lua_isfunction(L,-1))
+                               {
+                                       lua_pushvalue(L,1);
+                                       lua_pushvalue(L,2);
+                                       lua_pushvalue(L,3);
+                                       lua_call(L,3,0);
+                                       return 0;
+                               }
+                       }
+                       else
+                       {
+                               lua_pushstring(L,".set");
+                               lua_rawget(L,-2);                      /* stack: t k v mt tset */
+                               if (lua_istable(L,-1))
+                               {
+                                       lua_pushvalue(L,2);
+                                       lua_rawget(L,-2);                     /* stack: t k v mt tset func */
+                                       if (lua_iscfunction(L,-1))
+                                       {
+                                               lua_pushvalue(L,1);
+                                               lua_pushvalue(L,3);
+                                               lua_call(L,2,0);
+                                               return 0;
+                                       }
+                                       lua_pop(L,1);                          /* stack: t k v mt tset */
+                               }
+                               lua_pop(L,1);                           /* stack: t k v mt */
+                               if (!lua_getmetatable(L,-1))            /* stack: t k v mt mt */
+                                       lua_pushnil(L);
+                               lua_remove(L,-2);                       /* stack: t k v mt */
+                       }
+               }
+        lua_settop(L,3);                          /* stack: t k v */
+
+               /* then, store as a new field */
+               storeatubox(L,1);
+       }
+       else if (t== LUA_TTABLE)
+       {
+               module_newindex_event(L);
+       }
+       return 0;
+}
+
+static int class_call_event(lua_State* L) {
+
+       if (lua_istable(L, 1)) {
+               lua_pushstring(L, ".call");
+               lua_rawget(L, 1);
+               if (lua_isfunction(L, -1)) {
+
+                       lua_insert(L, 1);
+                       lua_call(L, lua_gettop(L)-1, 1);
+
+                       return 1;
+               };
+       };
+       tolua_error(L,"Attempt to call a non-callable object.",NULL);
+       return 0;
+};
+
+static int do_operator (lua_State* L, const char* op)
+{
+       if (lua_isuserdata(L,1))
+       {
+               /* Try metatables */
+               lua_pushvalue(L,1);                     /* stack: op1 op2 */
+               while (lua_getmetatable(L,-1))
+               {                                       /* stack: op1 op2 op1 mt */
+                       lua_remove(L,-2);                      /* stack: op1 op2 mt */
+                       lua_pushstring(L,op);                  /* stack: op1 op2 mt key */
+                       lua_rawget(L,-2);                      /* stack: obj key mt func */
+                       if (lua_isfunction(L,-1))
+                       {
+                               lua_pushvalue(L,1);
+                               lua_pushvalue(L,2);
+                               lua_call(L,2,1);
+                               return 1;
+                       }
+                       lua_settop(L,3);
+               }
+       }
+       tolua_error(L,"Attempt to perform operation on an invalid operand",NULL);
+       return 0;
+}
+
+static int class_add_event (lua_State* L)
+{
+       return do_operator(L,".add");
+}
+
+static int class_sub_event (lua_State* L)
+{
+       return do_operator(L,".sub");
+}
+
+static int class_mul_event (lua_State* L)
+{
+       return do_operator(L,".mul");
+}
+
+static int class_div_event (lua_State* L)
+{
+       return do_operator(L,".div");
+}
+
+static int class_lt_event (lua_State* L)
+{
+       return do_operator(L,".lt");
+}
+
+static int class_le_event (lua_State* L)
+{
+       return do_operator(L,".le");
+}
+
+static int class_eq_event (lua_State* L)
+{
+       /* copying code from do_operator here to return false when no operator is found */
+       if (lua_isuserdata(L,1))
+       {
+               /* Try metatables */
+               lua_pushvalue(L,1);                     /* stack: op1 op2 */
+               while (lua_getmetatable(L,-1))
+               {                                       /* stack: op1 op2 op1 mt */
+                       lua_remove(L,-2);                      /* stack: op1 op2 mt */
+                       lua_pushstring(L,".eq");                  /* stack: op1 op2 mt key */
+                       lua_rawget(L,-2);                      /* stack: obj key mt func */
+                       if (lua_isfunction(L,-1))
+                       {
+                               lua_pushvalue(L,1);
+                               lua_pushvalue(L,2);
+                               lua_call(L,2,1);
+                               return 1;
+                       }
+                       lua_settop(L,3);
+               }
+       }
+
+       lua_settop(L, 3);
+       lua_pushboolean(L, 0);
+       return 1;
+}
+
+/*
+static int class_gc_event (lua_State* L)
+{
+       void* u = *((void**)lua_touserdata(L,1));
+       fprintf(stderr, "collecting: looking at %p\n", u);
+       lua_pushstring(L,"tolua_gc");
+       lua_rawget(L,LUA_REGISTRYINDEX);
+       lua_pushlightuserdata(L,u);
+       lua_rawget(L,-2);
+       if (lua_isfunction(L,-1))
+       {
+               lua_pushvalue(L,1);
+               lua_call(L,1,0);
+               lua_pushlightuserdata(L,u);
+               lua_pushnil(L);
+               lua_rawset(L,-3);
+       }
+       lua_pop(L,2);
+       return 0;
+}
+*/
+TOLUA_API int class_gc_event (lua_State* L)
+{
+       void* u = *((void**)lua_touserdata(L,1));
+       int top;
+       /*fprintf(stderr, "collecting: looking at %p\n", u);*/
+       /*
+       lua_pushstring(L,"tolua_gc");
+       lua_rawget(L,LUA_REGISTRYINDEX);
+       */
+       lua_pushvalue(L, lua_upvalueindex(1));
+       lua_pushlightuserdata(L,u);
+       lua_rawget(L,-2);            /* stack: gc umt    */
+       lua_getmetatable(L,1);       /* stack: gc umt mt */
+       /*fprintf(stderr, "checking type\n");*/
+       top = lua_gettop(L);
+       if (tolua_fast_isa(L,top,top-1, lua_upvalueindex(2))) /* make sure we collect correct type */
+       {
+               /*fprintf(stderr, "Found type!\n");*/
+               /* get gc function */
+               lua_pushliteral(L,".collector");
+               lua_rawget(L,-2);           /* stack: gc umt mt collector */
+               if (lua_isfunction(L,-1)) {
+                       /*fprintf(stderr, "Found .collector!\n");*/
+               }
+               else {
+                       lua_pop(L,1);
+                       /*fprintf(stderr, "Using default cleanup\n");*/
+                       lua_pushcfunction(L,tolua_default_collect);
+               }
+
+               lua_pushvalue(L,1);         /* stack: gc umt mt collector u */
+               lua_call(L,1,0);
+
+               lua_pushlightuserdata(L,u); /* stack: gc umt mt u */
+               lua_pushnil(L);             /* stack: gc umt mt u nil */
+               lua_rawset(L,-5);           /* stack: gc umt mt */
+       }
+       lua_pop(L,3);
+       return 0;
+}
+
+
+/* Register module events
+       * It expects the metatable on the top of the stack
+*/
+TOLUA_API void tolua_moduleevents (lua_State* L)
+{
+       lua_pushstring(L,"__index");
+       lua_pushcfunction(L,module_index_event);
+       lua_rawset(L,-3);
+       lua_pushstring(L,"__newindex");
+       lua_pushcfunction(L,module_newindex_event);
+       lua_rawset(L,-3);
+}
+
+/* Check if the object on the top has a module metatable
+*/
+TOLUA_API int tolua_ismodulemetatable (lua_State* L)
+{
+       int r = 0;
+       if (lua_getmetatable(L,-1))
+       {
+               lua_pushstring(L,"__index");
+               lua_rawget(L,-2);
+               r = (lua_tocfunction(L,-1) == module_index_event);
+               lua_pop(L,2);
+       }
+       return r;
+}
+
+/* Register class events
+       * It expects the metatable on the top of the stack
+*/
+TOLUA_API void tolua_classevents (lua_State* L)
+{
+       lua_pushstring(L,"__index");
+       lua_pushcfunction(L,class_index_event);
+       lua_rawset(L,-3);
+       lua_pushstring(L,"__newindex");
+       lua_pushcfunction(L,class_newindex_event);
+       lua_rawset(L,-3);
+
+       lua_pushstring(L,"__add");
+       lua_pushcfunction(L,class_add_event);
+       lua_rawset(L,-3);
+       lua_pushstring(L,"__sub");
+       lua_pushcfunction(L,class_sub_event);
+       lua_rawset(L,-3);
+       lua_pushstring(L,"__mul");
+       lua_pushcfunction(L,class_mul_event);
+       lua_rawset(L,-3);
+       lua_pushstring(L,"__div");
+       lua_pushcfunction(L,class_div_event);
+       lua_rawset(L,-3);
+
+       lua_pushstring(L,"__lt");
+       lua_pushcfunction(L,class_lt_event);
+       lua_rawset(L,-3);
+       lua_pushstring(L,"__le");
+       lua_pushcfunction(L,class_le_event);
+       lua_rawset(L,-3);
+       lua_pushstring(L,"__eq");
+       lua_pushcfunction(L,class_eq_event);
+       lua_rawset(L,-3);
+
+       lua_pushstring(L,"__call");
+       lua_pushcfunction(L,class_call_event);
+       lua_rawset(L,-3);
+
+       lua_pushstring(L,"__gc");
+       lua_pushstring(L, "tolua_gc_event");
+       lua_rawget(L, LUA_REGISTRYINDEX);
+       /*lua_pushcfunction(L,class_gc_event);*/
+       lua_rawset(L,-3);
+}
+
diff --git a/tolua_event.h b/tolua_event.h
new file mode 100644 (file)
index 0000000..898f33d
--- /dev/null
@@ -0,0 +1,24 @@
+/* tolua: event functions
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#ifndef TOLUA_EVENT_H
+#define TOLUA_EVENT_H
+
+#include "tolua++.h"
+
+TOLUA_API void tolua_moduleevents (lua_State* L);
+TOLUA_API int tolua_ismodulemetatable (lua_State* L);
+TOLUA_API void tolua_classevents (lua_State* L);
+
+#endif
diff --git a/tolua_is.c b/tolua_is.c
new file mode 100644 (file)
index 0000000..add337d
--- /dev/null
@@ -0,0 +1,621 @@
+/* tolua: functions to check types.
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "tolua++.h"
+#include "lauxlib.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* a fast check if a is b, without parameter validation
+ i.e. if b is equal to a or a superclass of a. */
+TOLUA_API int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int super_index)
+{
+ int result;
+       if (lua_rawequal(L,mt_indexa,mt_indexb))
+               result = 1;
+       else
+       {
+               if (super_index) {
+                       lua_pushvalue(L, super_index);
+               } else {
+                       lua_pushliteral(L,"tolua_super");
+                       lua_rawget(L,LUA_REGISTRYINDEX);  /* stack: super */
+               };
+               lua_pushvalue(L,mt_indexa);       /* stack: super mta */
+               lua_rawget(L,-2);                 /* stack: super super[mta] */
+               lua_pushvalue(L,mt_indexb);       /* stack: super super[mta] mtb */
+               lua_rawget(L,LUA_REGISTRYINDEX);  /* stack: super super[mta] typenameB */
+               lua_rawget(L,-2);                 /* stack: super super[mta] bool */
+               result = lua_toboolean(L,-1);
+               lua_pop(L,3);
+       }
+       return result;
+}
+
+/* Push and returns the corresponding object typename */
+TOLUA_API const char* tolua_typename (lua_State* L, int lo)
+{
+       int tag = lua_type(L,lo);
+ if (tag == LUA_TNONE)
+  lua_pushstring(L,"[no object]");
+ else if (tag != LUA_TUSERDATA && tag != LUA_TTABLE)
+  lua_pushstring(L,lua_typename(L,tag));
+ else if (tag == LUA_TUSERDATA)
+ {
+  if (!lua_getmetatable(L,lo))
+   lua_pushstring(L,lua_typename(L,tag));
+               else
+               {
+                lua_rawget(L,LUA_REGISTRYINDEX);
+                if (!lua_isstring(L,-1))
+                       {
+                 lua_pop(L,1);
+                               lua_pushstring(L,"[undefined]");
+                       }
+               }
+       }
+       else  /* is table */
+       {
+               lua_pushvalue(L,lo);
+               lua_rawget(L,LUA_REGISTRYINDEX);
+               if (!lua_isstring(L,-1))
+               {
+                       lua_pop(L,1);
+                       lua_pushstring(L,"table");
+               }
+               else
+               {
+   lua_pushstring(L,"class ");
+                       lua_insert(L,-2);
+                       lua_concat(L,2);
+               }
+       }
+       return lua_tostring(L,-1);
+}
+
+TOLUA_API void tolua_error (lua_State* L, const char* msg, tolua_Error* err)
+{
+       if (msg[0] == '#')
+       {
+  const char* expected = err->type;
+               const char* provided = tolua_typename(L,err->index);
+  if (msg[1]=='f')
+  {
+   int narg = err->index;
+                       if (err->array)
+    luaL_error(L,"%s\n     argument #%d is array of '%s'; array of '%s' expected.\n",
+               msg+2,narg,provided,expected);
+                       else
+    luaL_error(L,"%s\n     argument #%d is '%s'; '%s' expected.\n",
+               msg+2,narg,provided,expected);
+  }
+  else if (msg[1]=='v')
+               {
+                       if (err->array)
+    luaL_error(L,"%s\n     value is array of '%s'; array of '%s' expected.\n",
+               msg+2,provided,expected);
+                       else
+    luaL_error(L,"%s\n     value is '%s'; '%s' expected.\n",
+               msg+2,provided,expected);
+               }
+ }
+ else
+  luaL_error(L,msg);
+}
+
+/* the equivalent of lua_is* for usertable */
+static  int lua_isusertable (lua_State* L, int lo, const const char* type)
+{
+       int r = 0;
+       if (lo < 0) lo = lua_gettop(L)+lo+1;
+       lua_pushvalue(L,lo);
+       lua_rawget(L,LUA_REGISTRYINDEX);  /* get registry[t] */
+       if (lua_isstring(L,-1))
+       {
+               r = strcmp(lua_tostring(L,-1),type)==0;
+               if (!r)
+               {
+                       /* try const */
+                       lua_pushstring(L,"const ");
+                       lua_insert(L,-2);
+                       lua_concat(L,2);
+                       r = lua_isstring(L,-1) && strcmp(lua_tostring(L,-1),type)==0;
+               }
+       }
+       lua_pop(L, 1);
+       return r;
+}
+
+int push_table_instance(lua_State* L, int lo) {
+
+       if (lua_istable(L, lo)) {
+
+               lua_pushstring(L, ".c_instance");
+               lua_gettable(L, lo);
+               if (lua_isuserdata(L, -1)) {
+
+                       lua_replace(L, lo);
+                       return 1;
+               } else {
+
+                       lua_pop(L, 1);
+                       return 0;
+               };
+       } else {
+               return 0;
+       };
+
+       return 0;
+};
+
+/* the equivalent of lua_is* for usertype */
+static int lua_isusertype (lua_State* L, int lo, const char* type)
+{
+       if (!lua_isuserdata(L,lo)) {
+               if (!push_table_instance(L, lo)) {
+                       return 0;
+               };
+       };
+       {
+               /* check if it is of the same type */
+               int r;
+               const char *tn;
+               if (lua_getmetatable(L,lo))        /* if metatable? */
+               {
+                lua_rawget(L,LUA_REGISTRYINDEX);  /* get registry[mt] */
+                tn = lua_tostring(L,-1);
+                r = tn && (strcmp(tn,type) == 0);
+                lua_pop(L, 1);
+                       if (r)
+                        return 1;
+                       else
+                       {
+                               /* check if it is a specialized class */
+                               lua_pushstring(L,"tolua_super");
+                               lua_rawget(L,LUA_REGISTRYINDEX); /* get super */
+                               lua_getmetatable(L,lo);
+                               lua_rawget(L,-2);                /* get super[mt] */
+                               if (lua_istable(L,-1))
+                               {
+                                       int b;
+                                       lua_pushstring(L,type);
+                                       lua_rawget(L,-2);                /* get super[mt][type] */
+                                       b = lua_toboolean(L,-1);
+                                       lua_pop(L,3);
+                                       if (b)
+                                        return 1;
+                               }
+                       }
+               }
+ }
+       return 0;
+}
+
+TOLUA_API int tolua_isnoobj (lua_State* L, int lo, tolua_Error* err)
+{
+ if (lua_gettop(L)<abs(lo))
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = "[no object]";
+ return 0;
+}
+
+TOLUA_API int tolua_isboolean (lua_State* L, int lo, int def, tolua_Error* err)
+{
+       if (def && lua_gettop(L)<abs(lo))
+               return 1;
+       if (lua_isnil(L,lo) || lua_isboolean(L,lo))
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = "boolean";
+       return 0;
+}
+
+TOLUA_API int tolua_isnumber (lua_State* L, int lo, int def, tolua_Error* err)
+{
+       if (def && lua_gettop(L)<abs(lo))
+               return 1;
+       if (lua_isnumber(L,lo))
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = "number";
+       return 0;
+}
+
+TOLUA_API int tolua_isstring (lua_State* L, int lo, int def, tolua_Error* err)
+{
+       if (def && lua_gettop(L)<abs(lo))
+               return 1;
+ if (lua_isnil(L,lo) || lua_isstring(L,lo))
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = "string";
+       return 0;
+}
+
+TOLUA_API int tolua_istable (lua_State* L, int lo, int def, tolua_Error* err)
+{
+       if (def && lua_gettop(L)<abs(lo))
+               return 1;
+       if (lua_istable(L,lo))
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = "table";
+       return 0;
+}
+
+TOLUA_API int tolua_isusertable (lua_State* L, int lo, const char* type, int def, tolua_Error* err)
+{
+       if (def && lua_gettop(L)<abs(lo))
+               return 1;
+       if (lua_isusertable(L,lo,type))
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = type;
+       return 0;
+}
+
+
+TOLUA_API int tolua_isuserdata (lua_State* L, int lo, int def, tolua_Error* err)
+{
+       if (def && lua_gettop(L)<abs(lo))
+               return 1;
+       if (lua_isnil(L,lo) || lua_isuserdata(L,lo))
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = "userdata";
+       return 0;
+}
+
+TOLUA_API int tolua_isvaluenil (lua_State* L, int lo, tolua_Error* err) {
+
+       if (lua_gettop(L)<abs(lo))
+               return 0; /* somebody else should chack this */
+       if (!lua_isnil(L, lo))
+               return 0;
+       
+       err->index = lo;
+       err->array = 0;
+       err->type = "value";
+       return 1;
+};
+
+TOLUA_API int tolua_isvalue (lua_State* L, int lo, int def, tolua_Error* err)
+{
+       if (def || abs(lo)<=lua_gettop(L))  /* any valid index */
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = "value";
+       return 0;
+}
+
+TOLUA_API int tolua_isusertype (lua_State* L, int lo, const char* type, int def, tolua_Error* err)
+{
+       if (def && lua_gettop(L)<abs(lo))
+               return 1;
+       if (lua_isnil(L,lo) || lua_isusertype(L,lo,type))
+               return 1;
+       err->index = lo;
+       err->array = 0;
+       err->type = type;
+       return 0;
+}
+
+TOLUA_API int tolua_isvaluearray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+       if (!tolua_istable(L,lo,def,err))
+               return 0;
+       else
+               return 1;
+}
+
+TOLUA_API int tolua_isbooleanarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+       if (!tolua_istable(L,lo,def,err))
+               return 0;
+       else
+       {
+               int i;
+               for (i=1; i<=dim; ++i)
+               {
+                       lua_pushnumber(L,i);
+                       lua_gettable(L,lo);
+         if (!(lua_isnil(L,-1) || lua_isboolean(L,-1)) &&
+                                         !(def && lua_isnil(L,-1))
+                                               )
+                       {
+                               err->index = lo;
+                               err->array = 1;
+                               err->type = "boolean";
+                               return 0;
+                       }
+                       lua_pop(L,1);
+               }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_isnumberarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+       if (!tolua_istable(L,lo,def,err))
+               return 0;
+       else
+       {
+               int i;
+               for (i=1; i<=dim; ++i)
+               {
+                       lua_pushnumber(L,i);
+                       lua_gettable(L,lo);
+                       if (!lua_isnumber(L,-1) &&
+                                         !(def && lua_isnil(L,-1))
+                                               )
+                       {
+                               err->index = lo;
+                               err->array = 1;
+                               err->type = "number";
+                               return 0;
+                       }
+                       lua_pop(L,1);
+               }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_isstringarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+       if (!tolua_istable(L,lo,def,err))
+               return 0;
+       else
+       {
+               int i;
+               for (i=1; i<=dim; ++i)
+               {
+                       lua_pushnumber(L,i);
+                       lua_gettable(L,lo);
+   if (!(lua_isnil(L,-1) || lua_isstring(L,-1)) &&
+                           !(def && lua_isnil(L,-1))
+                                               )
+                       {
+                               err->index = lo;
+                               err->array = 1;
+                               err->type = "string";
+                               return 0;
+                       }
+                       lua_pop(L,1);
+               }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_istablearray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+       if (!tolua_istable(L,lo,def,err))
+               return 0;
+       else
+       {
+               int i;
+               for (i=1; i<=dim; ++i)
+               {
+                       lua_pushnumber(L,i);
+                       lua_gettable(L,lo);
+         if (! lua_istable(L,-1) &&
+                           !(def && lua_isnil(L,-1))
+                                               )
+                       {
+                               err->index = lo;
+                               err->array = 1;
+                               err->type = "table";
+                               return 0;
+                       }
+                       lua_pop(L,1);
+               }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_isuserdataarray
+ (lua_State* L, int lo, int dim, int def, tolua_Error* err)
+{
+       if (!tolua_istable(L,lo,def,err))
+               return 0;
+       else
+       {
+               int i;
+               for (i=1; i<=dim; ++i)
+               {
+                       lua_pushnumber(L,i);
+                       lua_gettable(L,lo);
+         if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
+                           !(def && lua_isnil(L,-1))
+                                               )
+                       {
+                               err->index = lo;
+                               err->array = 1;
+                               err->type = "userdata";
+                               return 0;
+                       }
+                       lua_pop(L,1);
+               }
+ }
+ return 1;
+}
+
+TOLUA_API int tolua_isusertypearray
+ (lua_State* L, int lo, const char* type, int dim, int def, tolua_Error* err)
+{
+       if (!tolua_istable(L,lo,def,err))
+               return 0;
+       else
+       {
+               int i;
+               for (i=1; i<=dim; ++i)
+               {
+                       lua_pushnumber(L,i);
+                       lua_gettable(L,lo);
+         if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
+                           !(def && lua_isnil(L,-1))
+                                               )
+                       {
+                               err->index = lo;
+                               err->type = type;
+                               err->array = 1;
+                               return 0;
+                       }
+                       lua_pop(L,1);
+               }
+ }
+ return 1;
+}
+
+#if 0
+int tolua_isbooleanfield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+       lua_pushnumber(L,i);
+       lua_gettable(L,lo);
+       if (!(lua_isnil(L,-1) || lua_isboolean(L,-1)) &&
+                         !(def && lua_isnil(L,-1))
+                               )
+       {
+               err->index = lo;
+               err->array = 1;
+               err->type = "boolean";
+               return 0;
+       }
+       lua_pop(L,1);
+ return 1;
+}
+
+int tolua_isnumberfield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+       lua_pushnumber(L,i);
+       lua_gettable(L,lo);
+       if (!lua_isnumber(L,-1) &&
+                         !(def && lua_isnil(L,-1))
+                               )
+       {
+               err->index = lo;
+               err->array = 1;
+               err->type = "number";
+               return 0;
+       }
+       lua_pop(L,1);
+ return 1;
+}
+
+int tolua_isstringfield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+       lua_pushnumber(L,i);
+       lua_gettable(L,lo);
+ if (!(lua_isnil(L,-1) || lua_isstring(L,-1)) &&
+           !(def && lua_isnil(L,-1))
+                               )
+       {
+               err->index = lo;
+               err->array = 1;
+               err->type = "string";
+               return 0;
+       }
+       lua_pop(L,1);
+ return 1;
+}
+
+int tolua_istablefield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+       lua_pushnumber(L,i+1);
+       lua_gettable(L,lo);
+       if (! lua_istable(L,-1) &&
+           !(def && lua_isnil(L,-1))
+                               )
+       {
+               err->index = lo;
+               err->array = 1;
+               err->type = "table";
+               return 0;
+       }
+       lua_pop(L,1);
+}
+
+int tolua_isusertablefield
+ (lua_State* L, int lo, const char* type, int i, int def, tolua_Error* err)
+{
+       lua_pushnumber(L,i);
+       lua_gettable(L,lo);
+       if (! lua_isusertable(L,-1,type) &&
+           !(def && lua_isnil(L,-1))
+                               )
+       {
+               err->index = lo;
+               err->array = 1;
+               err->type = type;
+               return 0;
+       }
+       lua_pop(L,1);
+ return 1;
+}
+
+int tolua_isuserdatafield
+ (lua_State* L, int lo, int i, int def, tolua_Error* err)
+{
+       lua_pushnumber(L,i);
+       lua_gettable(L,lo);
+       if (!(lua_isnil(L,-1) || lua_isuserdata(L,-1)) &&
+           !(def && lua_isnil(L,-1))
+                               )
+       {
+               err->index = lo;
+               err->array = 1;
+               err->type = "userdata";
+               return 0;
+       }
+       lua_pop(L,1);
+ return 1;
+}
+
+int tolua_isusertypefield
+ (lua_State* L, int lo, const char* type, int i, int def, tolua_Error* err)
+{
+       lua_pushnumber(L,i);
+       lua_gettable(L,lo);
+       if (!(lua_isnil(L,-1) || lua_isusertype(L,-1,type)) &&
+           !(def && lua_isnil(L,-1))
+                               )
+       {
+               err->index = lo;
+               err->type = type;
+               err->array = 1;
+               return 0;
+       }
+       lua_pop(L,1);
+ return 1;
+}
+
+#endif
diff --git a/tolua_map.c b/tolua_map.c
new file mode 100644 (file)
index 0000000..d00e706
--- /dev/null
@@ -0,0 +1,704 @@
+/* tolua: functions to map features
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "tolua++.h"
+#include "tolua_event.h"
+#include "lauxlib.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+
+/* Create metatable
+       * Create and register new metatable
+*/
+static int tolua_newmetatable (lua_State* L, char* name)
+{
+       int r = luaL_newmetatable(L,name);
+
+       #ifdef LUA_VERSION_NUM /* only lua 5.1 */
+       if (r) {
+               lua_pushvalue(L, -1);
+               lua_pushstring(L, name);
+               lua_settable(L, LUA_REGISTRYINDEX); /* reg[mt] = type_name */
+       };
+       #endif
+
+       if (r)
+               tolua_classevents(L); /* set meta events */
+       lua_pop(L,1);
+       return r;
+}
+
+/* Map super classes
+       * It sets 'name' as being also a 'base', mapping all super classes of 'base' in 'name'
+*/
+static void mapsuper (lua_State* L, const char* name, const char* base)
+{
+       /* push registry.super */
+ lua_pushstring(L,"tolua_super");
+ lua_rawget(L,LUA_REGISTRYINDEX);    /* stack: super */
+       luaL_getmetatable(L,name);          /* stack: super mt */
+ lua_rawget(L,-2);                   /* stack: super table */
+       if (lua_isnil(L,-1))
+       {
+        /* create table */
+               lua_pop(L,1);
+        lua_newtable(L);                    /* stack: super table */
+        luaL_getmetatable(L,name);          /* stack: super table mt */
+               lua_pushvalue(L,-2);                /* stack: super table mt table */
+               lua_rawset(L,-4);                   /* stack: super table */
+       }
+
+       /* set base as super class */
+       lua_pushstring(L,base);
+       lua_pushboolean(L,1);
+       lua_rawset(L,-3);                    /* stack: super table */
+
+       /* set all super class of base as super class of name */
+       luaL_getmetatable(L,base);          /* stack: super table base_mt */
+       lua_rawget(L,-3);                   /* stack: super table base_table */
+       if (lua_istable(L,-1))
+       {
+               /* traverse base table */
+               lua_pushnil(L);  /* first key */
+               while (lua_next(L,-2) != 0)
+               {
+                       /* stack: ... base_table key value */
+                       lua_pushvalue(L,-2);    /* stack: ... base_table key value key */
+                       lua_insert(L,-2);       /* stack: ... base_table key key value */
+                       lua_rawset(L,-5);       /* stack: ... base_table key */
+               }
+       }
+       lua_pop(L,3);                       /* stack: <empty> */
+}
+
+/* creates a 'tolua_ubox' table for base clases, and
+// expects the metatable and base metatable on the stack */
+static void set_ubox(lua_State* L) {
+
+       /* mt basemt */
+       if (!lua_isnil(L, -1)) {
+               lua_pushstring(L, "tolua_ubox");
+               lua_rawget(L,-2);
+       } else {
+               lua_pushnil(L);
+       };
+       /* mt basemt base_ubox */
+       if (!lua_isnil(L,-1)) {
+               lua_pushstring(L, "tolua_ubox");
+               lua_insert(L, -2);
+               /* mt basemt key ubox */
+               lua_rawset(L,-4);
+               /* (mt with ubox) basemt */
+       } else {
+               /* mt basemt nil */
+               lua_pop(L, 1);
+               lua_pushstring(L,"tolua_ubox"); lua_newtable(L);
+               /* make weak value metatable for ubox table to allow userdata to be
+               garbage-collected */
+               lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "v"); lua_rawset(L, -3);               /* stack: string ubox mt */
+               lua_setmetatable(L, -2);  /* stack:mt basemt string ubox */
+               lua_rawset(L,-4);
+       };
+
+};
+
+/* Map inheritance
+       * It sets 'name' as derived from 'base' by setting 'base' as metatable of 'name'
+*/
+static void mapinheritance (lua_State* L, const char* name, const char* base)
+{
+       /* set metatable inheritance */
+       luaL_getmetatable(L,name);
+
+       if (base && *base)
+               luaL_getmetatable(L,base);
+       else {
+
+               if (lua_getmetatable(L, -1)) { /* already has a mt, we don't overwrite it */
+                       lua_pop(L, 2);
+                       return;
+               };
+               luaL_getmetatable(L,"tolua_commonclass");
+       };
+
+       set_ubox(L);
+
+       lua_setmetatable(L,-2);
+       lua_pop(L,1);
+}
+
+/* Object type
+*/
+static int tolua_bnd_type (lua_State* L)
+{
+       tolua_typename(L,lua_gettop(L));
+       return 1;
+}
+
+/* Take ownership
+*/
+static int tolua_bnd_takeownership (lua_State* L)
+{
+       int success = 0;
+       if (lua_isuserdata(L,1))
+       {
+               if (lua_getmetatable(L,1))        /* if metatable? */
+               {
+                       lua_pop(L,1);             /* clear metatable off stack */
+                       /* force garbage collection to avoid C to reuse a to-be-collected address */
+                       #ifdef LUA_VERSION_NUM
+                       lua_gc(L, LUA_GCCOLLECT, 0);
+                       #else
+                       lua_setgcthreshold(L,0);
+                       #endif
+
+                       success = tolua_register_gc(L,1);
+               }
+       }
+       lua_pushboolean(L,success!=0);
+       return 1;
+}
+
+/* Release ownership
+*/
+static int tolua_bnd_releaseownership (lua_State* L)
+{
+       int done = 0;
+       if (lua_isuserdata(L,1))
+       {
+               void* u = *((void**)lua_touserdata(L,1));
+               /* force garbage collection to avoid releasing a to-be-collected address */
+               #ifdef LUA_VERSION_NUM
+               lua_gc(L, LUA_GCCOLLECT, 0);
+               #else
+               lua_setgcthreshold(L,0);
+               #endif
+               lua_pushstring(L,"tolua_gc");
+               lua_rawget(L,LUA_REGISTRYINDEX);
+               lua_pushlightuserdata(L,u);
+               lua_rawget(L,-2);
+               lua_getmetatable(L,1);
+               if (lua_rawequal(L,-1,-2))  /* check that we are releasing the correct type */
+               {
+                       lua_pushlightuserdata(L,u);
+                       lua_pushnil(L);
+                       lua_rawset(L,-5);
+                       done = 1;
+               }
+       }
+       lua_pushboolean(L,done!=0);
+       return 1;
+}
+
+/* Type casting
+*/
+static int tolua_bnd_cast (lua_State* L)
+{
+
+/* // old code
+        void* v = tolua_tousertype(L,1,NULL);
+        const char* s = tolua_tostring(L,2,NULL);
+        if (v && s)
+         tolua_pushusertype(L,v,s);
+        else
+         lua_pushnil(L);
+        return 1;
+*/
+
+       void* v;
+       const char* s;
+       if (lua_islightuserdata(L, 1)) {
+               v = tolua_touserdata(L, 1, NULL);
+       } else {
+               v = tolua_tousertype(L, 1, 0);
+       };
+
+       s = tolua_tostring(L,2,NULL);
+       if (v && s)
+        tolua_pushusertype(L,v,s);
+       else
+        lua_pushnil(L);
+       return 1;
+}
+
+/* Inheritance
+*/
+static int tolua_bnd_inherit (lua_State* L) {
+
+       /* stack: lua object, c object */
+       lua_pushstring(L, ".c_instance");
+       lua_pushvalue(L, -2);
+       lua_rawset(L, -4);
+       /* l_obj[".c_instance"] = c_obj */
+
+       return 0;
+};
+
+#ifdef LUA_VERSION_NUM /* lua 5.1 */
+static int tolua_bnd_setpeer(lua_State* L) {
+
+       /* stack: userdata, table */
+       if (!lua_isuserdata(L, -2)) {
+               lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected.");
+               lua_error(L);
+       };
+       
+       if (lua_isnil(L, -1)) {
+
+               lua_pop(L, 1);
+               lua_pushvalue(L, TOLUA_NOPEER);
+       };
+       lua_setfenv(L, -2);
+
+       return 0;
+};
+
+static int tolua_bnd_getpeer(lua_State* L) {
+
+       /* stack: userdata */
+       lua_getfenv(L, -1);
+       if (lua_rawequal(L, -1, TOLUA_NOPEER)) {
+               lua_pop(L, 1);
+               lua_pushnil(L);
+       };
+       return 1;
+};
+#endif
+
+/* static int class_gc_event (lua_State* L); */
+
+TOLUA_API void tolua_open (lua_State* L)
+{
+ int top = lua_gettop(L);
+ lua_pushstring(L,"tolua_opened");
+ lua_rawget(L,LUA_REGISTRYINDEX);
+ if (!lua_isboolean(L,-1))
+ {
+  lua_pushstring(L,"tolua_opened"); lua_pushboolean(L,1); lua_rawset(L,LUA_REGISTRYINDEX);
+
+  #ifndef LUA_VERSION_NUM /* only prior to lua 5.1 */
+  /* create peer object table */
+  lua_pushstring(L, "tolua_peers"); lua_newtable(L);
+  /* make weak key metatable for peers indexed by userdata object */
+  lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "k"); lua_rawset(L, -3);                /* stack: string peers mt */
+  lua_setmetatable(L, -2);   /* stack: string peers */
+  lua_rawset(L,LUA_REGISTRYINDEX);
+  #endif
+
+  /* create object ptr -> udata mapping table */
+  lua_pushstring(L,"tolua_ubox"); lua_newtable(L);
+  /* make weak value metatable for ubox table to allow userdata to be
+     garbage-collected */
+  lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "v"); lua_rawset(L, -3);               /* stack: string ubox mt */
+  lua_setmetatable(L, -2);  /* stack: string ubox */
+  lua_rawset(L,LUA_REGISTRYINDEX);
+
+  lua_pushstring(L,"tolua_super"); lua_newtable(L); lua_rawset(L,LUA_REGISTRYINDEX);
+  lua_pushstring(L,"tolua_gc"); lua_newtable(L);lua_rawset(L,LUA_REGISTRYINDEX);
+
+  /* create gc_event closure */
+  lua_pushstring(L, "tolua_gc_event");
+  lua_pushstring(L, "tolua_gc");
+  lua_rawget(L, LUA_REGISTRYINDEX);
+  lua_pushstring(L, "tolua_super");
+  lua_rawget(L, LUA_REGISTRYINDEX);
+  lua_pushcclosure(L, class_gc_event, 2);
+  lua_rawset(L, LUA_REGISTRYINDEX);
+
+  tolua_newmetatable(L,"tolua_commonclass");
+
+  tolua_module(L,NULL,0);
+  tolua_beginmodule(L,NULL);
+  tolua_module(L,"tolua",0);
+  tolua_beginmodule(L,"tolua");
+  tolua_function(L,"type",tolua_bnd_type);
+  tolua_function(L,"takeownership",tolua_bnd_takeownership);
+  tolua_function(L,"releaseownership",tolua_bnd_releaseownership);
+  tolua_function(L,"cast",tolua_bnd_cast);
+  tolua_function(L,"inherit", tolua_bnd_inherit);
+  #ifdef LUA_VERSION_NUM /* lua 5.1 */
+  tolua_function(L, "setpeer", tolua_bnd_setpeer);
+  tolua_function(L, "getpeer", tolua_bnd_getpeer);
+  #endif
+
+  tolua_endmodule(L);
+  tolua_endmodule(L);
+ }
+ lua_settop(L,top);
+}
+
+/* Copy a C object
+*/
+TOLUA_API void* tolua_copy (lua_State* L, void* value, unsigned int size)
+{
+       void* clone = (void*)malloc(size);
+       if (clone)
+        memcpy(clone,value,size);
+       else
+               tolua_error(L,"insuficient memory",NULL);
+       return clone;
+}
+
+/* Default collect function
+*/
+TOLUA_API int tolua_default_collect (lua_State* tolua_S)
+{
+ void* self = tolua_tousertype(tolua_S,1,0);
+ free(self);
+ return 0;
+}
+
+/* Do clone
+*/
+TOLUA_API int tolua_register_gc (lua_State* L, int lo)
+{
+ int success = 1;
+ void *value = *(void **)lua_touserdata(L,lo);
+ lua_pushstring(L,"tolua_gc");
+ lua_rawget(L,LUA_REGISTRYINDEX);
+       lua_pushlightuserdata(L,value);
+       lua_rawget(L,-2);
+       if (!lua_isnil(L,-1)) /* make sure that object is not already owned */
+               success = 0;
+       else
+       {
+               lua_pushlightuserdata(L,value);
+               lua_getmetatable(L,lo);
+               lua_rawset(L,-4);
+       }
+       lua_pop(L,2);
+       return success;
+}
+
+/* Register a usertype
+       * It creates the correspoding metatable in the registry, for both 'type' and 'const type'.
+       * It maps 'const type' as being also a 'type'
+*/
+TOLUA_API void tolua_usertype (lua_State* L, const char* type)
+{
+ char ctype[128] = "const ";
+ strncat(ctype,type,120);
+
+       /* create both metatables */
+ if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,type))
+        mapsuper(L,type,ctype);             /* 'type' is also a 'const type' */
+}
+
+
+/* Begin module
+       * It pushes the module (or class) table on the stack
+*/
+TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
+{
+       if (name)
+       {
+        lua_pushstring(L,name);
+               lua_rawget(L,-2);
+       }
+       else
+        lua_pushvalue(L,LUA_GLOBALSINDEX);
+}
+
+/* End module
+       * It pops the module (or class) from the stack
+*/
+TOLUA_API void tolua_endmodule (lua_State* L)
+{
+       lua_pop(L,1);
+}
+
+/* Map module
+       * It creates a new module
+*/
+#if 1
+TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
+{
+       if (name)
+       {
+               /* tolua module */
+               lua_pushstring(L,name);
+               lua_rawget(L,-2);
+               if (!lua_istable(L,-1))  /* check if module already exists */
+               {
+                       lua_pop(L,1);
+                lua_newtable(L);
+                lua_pushstring(L,name);
+                       lua_pushvalue(L,-2);
+                lua_rawset(L,-4);       /* assing module into module */
+               }
+       }
+       else
+       {
+               /* global table */
+               lua_pushvalue(L,LUA_GLOBALSINDEX);
+       }
+       if (hasvar)
+       {
+               if (!tolua_ismodulemetatable(L))  /* check if it already has a module metatable */
+               {
+                       /* create metatable to get/set C/C++ variable */
+                       lua_newtable(L);
+                       tolua_moduleevents(L);
+                       if (lua_getmetatable(L,-2))
+                               lua_setmetatable(L,-2);  /* set old metatable as metatable of metatable */
+                       lua_setmetatable(L,-2);
+               }
+       }
+       lua_pop(L,1);               /* pop module */
+}
+#else
+TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
+{
+       if (name)
+       {
+               /* tolua module */
+               lua_pushstring(L,name);
+               lua_newtable(L);
+       }
+       else
+       {
+               /* global table */
+               lua_pushvalue(L,LUA_GLOBALSINDEX);
+       }
+       if (hasvar)
+       {
+               /* create metatable to get/set C/C++ variable */
+               lua_newtable(L);
+               tolua_moduleevents(L);
+               if (lua_getmetatable(L,-2))
+                       lua_setmetatable(L,-2);  /* set old metatable as metatable of metatable */
+               lua_setmetatable(L,-2);
+       }
+       if (name)
+               lua_rawset(L,-3);       /* assing module into module */
+       else
+               lua_pop(L,1);           /* pop global table */
+}
+#endif
+
+static void push_collector(lua_State* L, const char* type, lua_CFunction col) {
+
+       /* push collector function, but only if it's not NULL, or if there's no
+          collector already */
+       if (!col) return;
+       luaL_getmetatable(L,type);
+       lua_pushstring(L,".collector");
+       /*
+       if (!col) {
+               lua_pushvalue(L, -1);
+               lua_rawget(L, -3);
+               if (!lua_isnil(L, -1)) {
+                       lua_pop(L, 3);
+                       return;
+               };
+               lua_pop(L, 1);
+       };
+       //      */
+       lua_pushcfunction(L,col);
+
+       lua_rawset(L,-3);
+       lua_pop(L, 1);
+};
+
+/* Map C class
+       * It maps a C class, setting the appropriate inheritance and super classes.
+*/
+TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col)
+{
+       char cname[128] = "const ";
+       char cbase[128] = "const ";
+       strncat(cname,name,120);
+       strncat(cbase,base,120);
+
+       mapinheritance(L,name,base);
+       mapinheritance(L,cname,name);
+
+       mapsuper(L,cname,cbase);
+       mapsuper(L,name,base);
+
+       lua_pushstring(L,lname);
+       
+       push_collector(L, name, col);
+       /*
+       luaL_getmetatable(L,name);
+       lua_pushstring(L,".collector");
+       lua_pushcfunction(L,col);
+
+       lua_rawset(L,-3);
+       */
+       
+       luaL_getmetatable(L,name);
+       lua_rawset(L,-3);              /* assign class metatable to module */
+
+       /* now we also need to store the collector table for the const
+          instances of the class */
+       push_collector(L, cname, col);
+       /*
+       luaL_getmetatable(L,cname);
+       lua_pushstring(L,".collector");
+       lua_pushcfunction(L,col);
+       lua_rawset(L,-3);
+       lua_pop(L,1);
+       */
+       
+
+}
+
+/* Add base
+       * It adds additional base classes to a class (for multiple inheritance)
+       * (not for now)
+TOLUA_API void tolua_addbase(lua_State* L, char* name, char* base) {
+
+       char cname[128] = "const ";
+       char cbase[128] = "const ";
+       strncat(cname,name,120);
+       strncat(cbase,base,120);
+
+       mapsuper(L,cname,cbase);
+       mapsuper(L,name,base);
+};
+*/
+
+/* Map function
+       * It assigns a function into the current module (or class)
+*/
+TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func)
+{
+ lua_pushstring(L,name);
+ lua_pushcfunction(L,func);
+       lua_rawset(L,-3);
+}
+
+/* sets the __call event for the class (expects the class' main table on top) */
+/*     never really worked :(
+TOLUA_API void tolua_set_call_event(lua_State* L, lua_CFunction func, char* type) {
+
+       lua_getmetatable(L, -1);
+       //luaL_getmetatable(L, type);
+       lua_pushstring(L,"__call");
+       lua_pushcfunction(L,func);
+       lua_rawset(L,-3);
+       lua_pop(L, 1);
+};
+*/
+
+/* Map constant number
+       * It assigns a constant number into the current module (or class)
+*/
+TOLUA_API void tolua_constant (lua_State* L, const char* name, lua_Number value)
+{
+       lua_pushstring(L,name);
+       tolua_pushnumber(L,value);
+       lua_rawset(L,-3);
+}
+
+
+/* Map variable
+       * It assigns a variable into the current module (or class)
+*/
+TOLUA_API void tolua_variable (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set)
+{
+       /* get func */
+       lua_pushstring(L,".get");
+       lua_rawget(L,-2);
+       if (!lua_istable(L,-1))
+       {
+               /* create .get table, leaving it at the top */
+               lua_pop(L,1);
+               lua_newtable(L);
+        lua_pushstring(L,".get");
+               lua_pushvalue(L,-2);
+               lua_rawset(L,-4);
+       }
+       lua_pushstring(L,name);
+       lua_pushcfunction(L,get);
+ lua_rawset(L,-3);                  /* store variable */
+       lua_pop(L,1);                      /* pop .get table */
+
+       /* set func */
+       if (set)
+       {
+               lua_pushstring(L,".set");
+               lua_rawget(L,-2);
+               if (!lua_istable(L,-1))
+               {
+                       /* create .set table, leaving it at the top */
+                       lua_pop(L,1);
+                       lua_newtable(L);
+                       lua_pushstring(L,".set");
+                       lua_pushvalue(L,-2);
+                       lua_rawset(L,-4);
+               }
+               lua_pushstring(L,name);
+               lua_pushcfunction(L,set);
+               lua_rawset(L,-3);                  /* store variable */
+               lua_pop(L,1);                      /* pop .set table */
+       }
+}
+
+/* Access const array
+       * It reports an error when trying to write into a const array
+*/
+static int const_array (lua_State* L)
+{
+ luaL_error(L,"value of const array cannot be changed");
+ return 0;
+}
+
+/* Map an array
+       * It assigns an array into the current module (or class)
+*/
+TOLUA_API void tolua_array (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set)
+{
+       lua_pushstring(L,".get");
+       lua_rawget(L,-2);
+       if (!lua_istable(L,-1))
+       {
+               /* create .get table, leaving it at the top */
+               lua_pop(L,1);
+               lua_newtable(L);
+        lua_pushstring(L,".get");
+               lua_pushvalue(L,-2);
+               lua_rawset(L,-4);
+       }
+       lua_pushstring(L,name);
+
+ lua_newtable(L);           /* create array metatable */
+ lua_pushvalue(L,-1);
+       lua_setmetatable(L,-2);    /* set the own table as metatable (for modules) */
+ lua_pushstring(L,"__index");
+ lua_pushcfunction(L,get);
+       lua_rawset(L,-3);
+ lua_pushstring(L,"__newindex");
+ lua_pushcfunction(L,set?set:const_array);
+       lua_rawset(L,-3);
+
+ lua_rawset(L,-3);                  /* store variable */
+       lua_pop(L,1);                      /* pop .get table */
+}
+
+
+TOLUA_API void tolua_dobuffer(lua_State* L, char* B, unsigned int size, const char* name) {
+
+ #ifdef LUA_VERSION_NUM /* lua 5.1 */
+ luaL_loadbuffer(L, B, size, name) || lua_pcall(L, 0, 0, 0);
+ #else
+ lua_dobuffer(L, B, size, name);
+ #endif
+};
+
diff --git a/tolua_push.c b/tolua_push.c
new file mode 100644 (file)
index 0000000..6394147
--- /dev/null
@@ -0,0 +1,171 @@
+/* tolua: functions to push C values.
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "tolua++.h"
+#include "lauxlib.h"
+
+#include <stdlib.h>
+
+TOLUA_API void tolua_pushvalue (lua_State* L, int lo)
+{
+ lua_pushvalue(L,lo);
+}
+
+TOLUA_API void tolua_pushboolean (lua_State* L, int value)
+{
+ lua_pushboolean(L,value);
+}
+
+TOLUA_API void tolua_pushnumber (lua_State* L, lua_Number value)
+{
+ lua_pushnumber(L,value);
+}
+
+TOLUA_API void tolua_pushstring (lua_State* L, const char* value)
+{
+ if (value == NULL)
+  lua_pushnil(L);
+ else
+  lua_pushstring(L,value);
+}
+
+TOLUA_API void tolua_pushuserdata (lua_State* L, void* value)
+{
+ if (value == NULL)
+  lua_pushnil(L);
+ else
+  lua_pushlightuserdata(L,value);
+}
+
+TOLUA_API void tolua_pushusertype (lua_State* L, void* value, const char* type)
+{
+ if (value == NULL)
+  lua_pushnil(L);
+ else
+ {
+  luaL_getmetatable(L, type);
+  lua_pushstring(L,"tolua_ubox");
+  lua_rawget(L,-2);        /* stack: mt ubox */
+  if (lua_isnil(L, -1)) {
+         lua_pop(L, 1);
+         lua_pushstring(L, "tolua_ubox");
+         lua_rawget(L, LUA_REGISTRYINDEX);
+  };
+  lua_pushlightuserdata(L,value);
+  lua_rawget(L,-2);                       /* stack: mt ubox ubox[u] */
+  if (lua_isnil(L,-1))
+  {
+   lua_pop(L,1);                          /* stack: mt ubox */
+   lua_pushlightuserdata(L,value);
+   *(void**)lua_newuserdata(L,sizeof(void *)) = value;   /* stack: mt ubox u newud */
+   lua_pushvalue(L,-1);                   /* stack: mt ubox u newud newud */
+   lua_insert(L,-4);                      /* stack: mt newud ubox u newud */
+   lua_rawset(L,-3);                      /* stack: mt newud ubox */
+   lua_pop(L,1);                          /* stack: mt newud */
+   /*luaL_getmetatable(L,type);*/
+   lua_pushvalue(L, -2);                       /* stack: mt newud mt */
+   lua_setmetatable(L,-2);                     /* stack: mt newud */
+
+   #ifdef LUA_VERSION_NUM
+   lua_pushvalue(L, TOLUA_NOPEER);
+   lua_setfenv(L, -2);
+   #endif
+  }
+  else
+  {
+   /* check the need of updating the metatable to a more specialized class */
+   lua_insert(L,-2);                       /* stack: mt ubox[u] ubox */
+   lua_pop(L,1);                           /* stack: mt ubox[u] */
+   lua_pushstring(L,"tolua_super");
+   lua_rawget(L,LUA_REGISTRYINDEX);        /* stack: mt ubox[u] super */
+   lua_getmetatable(L,-2);                 /* stack: mt ubox[u] super mt */
+   lua_rawget(L,-2);                       /* stack: mt ubox[u] super super[mt] */
+                       if (lua_istable(L,-1))
+                       {
+                               lua_pushstring(L,type);                 /* stack: mt ubox[u] super super[mt] type */
+                               lua_rawget(L,-2);                       /* stack: mt ubox[u] super super[mt] flag */
+                               if (lua_toboolean(L,-1) == 1)   /* if true */
+                               {
+                                       lua_pop(L,3);   /* mt ubox[u]*/
+                                       lua_remove(L, -2);
+                                       return;
+                               }
+                       }
+                       /* type represents a more specilized type */
+                       /*luaL_getmetatable(L,type);             // stack: mt ubox[u] super super[mt] flag mt */
+                       lua_pushvalue(L, -5);                                   /* stack: mt ubox[u] super super[mt] flag mt */
+                       lua_setmetatable(L,-5);                /* stack: mt ubox[u] super super[mt] flag */
+                       lua_pop(L,3);                          /* stack: mt ubox[u] */
+  }
+  lua_remove(L, -2);   /* stack: ubox[u]*/
+ }
+}
+
+TOLUA_API void tolua_pushusertype_and_takeownership (lua_State* L, void* value, const char* type)
+{
+       tolua_pushusertype(L,value,type);
+       tolua_register_gc(L,lua_gettop(L));
+}
+
+TOLUA_API void tolua_pushfieldvalue (lua_State* L, int lo, int index, int v)
+{
+ lua_pushnumber(L,index);
+ lua_pushvalue(L,v);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfieldboolean (lua_State* L, int lo, int index, int v)
+{
+ lua_pushnumber(L,index);
+ lua_pushboolean(L,v);
+ lua_settable(L,lo);
+}
+
+
+TOLUA_API void tolua_pushfieldnumber (lua_State* L, int lo, int index, lua_Number v)
+{
+ lua_pushnumber(L,index);
+ tolua_pushnumber(L,v);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfieldstring (lua_State* L, int lo, int index, const char* v)
+{
+ lua_pushnumber(L,index);
+ tolua_pushstring(L,v);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfielduserdata (lua_State* L, int lo, int index, void* v)
+{
+ lua_pushnumber(L,index);
+ tolua_pushuserdata(L,v);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfieldusertype (lua_State* L, int lo, int index, void* v, const char* type)
+{
+ lua_pushnumber(L,index);
+ tolua_pushusertype(L,v,type);
+ lua_settable(L,lo);
+}
+
+TOLUA_API void tolua_pushfieldusertype_and_takeownership (lua_State* L, int lo, int index, void* v, const char* type)
+{
+ lua_pushnumber(L,index);
+ tolua_pushusertype(L,v,type);
+       tolua_register_gc(L,lua_gettop(L));
+ lua_settable(L,lo);
+}
+
diff --git a/tolua_to.c b/tolua_to.c
new file mode 100644 (file)
index 0000000..542ca67
--- /dev/null
@@ -0,0 +1,133 @@
+/* tolua: funcitons to convert to C types
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Apr 2003
+** $Id: $
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "tolua++.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+TOLUA_API lua_Number tolua_tonumber (lua_State* L, int narg, lua_Number def)
+{
+ return lua_gettop(L)<abs(narg) ? def : lua_tonumber(L,narg);
+}
+
+TOLUA_API const char* tolua_tostring (lua_State* L, int narg, const char* def)
+{
+ return lua_gettop(L)<abs(narg) ? def : lua_tostring(L,narg);
+}
+
+TOLUA_API void* tolua_touserdata (lua_State* L, int narg, void* def)
+{
+       
+       /* return lua_gettop(L)<abs(narg) ? def : lua_touserdata(L,narg); */
+
+       if (lua_gettop(L)<abs(narg)) {
+               return def;
+       };
+        
+       if (lua_islightuserdata(L, narg)) {
+       
+               return lua_touserdata(L,narg);
+       };
+       
+       return tolua_tousertype(L, narg, def);
+}
+
+extern int push_table_instance(lua_State* L, int lo);
+
+TOLUA_API void* tolua_tousertype (lua_State* L, int narg, void* def)
+{
+ if (lua_gettop(L)<abs(narg))
+  return def;
+ else
+ {
+  void* u;
+  if (!lua_isuserdata(L, narg)) {
+         if (!push_table_instance(L, narg)) return NULL;
+  };
+  u = lua_touserdata(L,narg);
+  return (u==NULL) ? NULL : *((void**)u); /* nil represents NULL */
+ }
+}
+
+TOLUA_API int tolua_tovalue (lua_State* L, int narg, int def)
+{
+ return lua_gettop(L)<abs(narg) ? def : narg;
+}
+
+TOLUA_API int tolua_toboolean (lua_State* L, int narg, int def)
+{
+ return lua_gettop(L)<abs(narg) ?  def : lua_toboolean(L,narg);
+}
+
+TOLUA_API lua_Number tolua_tofieldnumber (lua_State* L, int lo, int index, lua_Number def)
+{
+ double v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : lua_tonumber(L,-1);
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API const char* tolua_tofieldstring
+(lua_State* L, int lo, int index, const char* def)
+{
+ const char* v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : lua_tostring(L,-1);
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API void* tolua_tofielduserdata (lua_State* L, int lo, int index, void* def)
+{
+ void* v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : lua_touserdata(L,-1);
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API void* tolua_tofieldusertype (lua_State* L, int lo, int index, void* def)
+{
+ void* v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : (*(void **)(lua_touserdata(L, -1))); /* lua_unboxpointer(L,-1); */
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API int tolua_tofieldvalue (lua_State* L, int lo, int index, int def)
+{
+ int v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? def : lo;
+ lua_pop(L,1);
+ return v;
+}
+
+TOLUA_API int tolua_getfieldboolean (lua_State* L, int lo, int index, int def)
+{
+ int v;
+ lua_pushnumber(L,index);
+ lua_gettable(L,lo);
+ v = lua_isnil(L,-1) ? 0 : lua_toboolean(L,-1);
+ lua_pop(L,1);
+ return v;
+}