text:
/* 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
	#if LUA_VERSION_NUM > 501
		lua_getuservalue(L, lo);
	#else
		lua_getfenv(L, lo);
	#endif

		if (lua_rawequal(L, -1, TOLUA_NOPEER)) {
			lua_pop(L, 1);
			lua_newtable(L);
			lua_pushvalue(L, -1);
			#if LUA_VERSION_NUM > 501
				lua_setuservalue(L, lo);	/* stack: k,v,table  */
			#else
				lua_setfenv(L, lo);	/* stack: k,v,table  */
			#endif
		};
		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 */
		#if LUA_VERSION_NUM > 501
			lua_getuservalue(L, 1);
		#else
			lua_getfenv(L, 1);
		#endif

		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)
{
	if (lua_type(L, 1) == LUA_TUSERDATA) {
		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_pushstring(L, "tolua_gc");
		lua_rawget(L, LUA_REGISTRYINDEX);

		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);
}


text:
#ifndef __TOLUA_FIX_H_
#define __TOLUA_FIX_H_

#include "tolua++.h"

#define TOLUA_REFID_PTR_MAPPING "toluafix_refid_ptr_mapping"
#define TOLUA_REFID_TYPE_MAPPING "toluafix_refid_type_mapping"
#define TOLUA_REFID_FUNCTION_MAPPING "toluafix_refid_function_mapping"

TOLUA_API void toluafix_open(lua_State* L);
TOLUA_API int toluafix_ref_function(lua_State* L, int lo, int def);
TOLUA_API void toluafix_get_function_by_refid(lua_State* L, int refid);
TOLUA_API void toluafix_remove_function_by_refid(lua_State* L, int refid);

#endif // __TOLUA_FIX_H_

mime_type: text/plain


text:
/* 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);
	}

	#if LUA_VERSION_NUM > 501
		lua_setuservalue(L, -2);
	#else
		lua_setfenv(L, -2);
	#endif

	return 0;
};

static int tolua_bnd_getpeer(lua_State* L) {

	/* stack: userdata */
	#if LUA_VERSION_NUM > 501
		lua_getuservalue(L, -1);
	#else
		lua_getfenv(L, -1);
	#endif
	if (lua_rawequal(L, -1, TOLUA_NOPEER)) {
		lua_pop(L, 1);
		lua_pushnil(L);
		lua_rawget(L, -2);
	}
	else
	#if LUA_VERSION_NUM > 501
		lua_pushglobaltable(L);
	#else
		lua_pushvalue(L, LUA_GLOBALSINDEX);
	#endif
	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
	#if LUA_VERSION_NUM > 501
		lua_pushglobaltable(L);
	#else
		lua_pushvalue(L, LUA_GLOBALSINDEX);
	#endif
}

/* 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 */
		#if LUA_VERSION_NUM > 501
			lua_pushglobaltable(L);
		#else
			lua_pushvalue(L, LUA_GLOBALSINDEX);
		#endif
	}
	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 */
	#if LUA_VERSION_NUM > 501
		lua_pushglobaltable(L);
	#else
		lua_pushvalue(L, LUA_GLOBALSINDEX);
	#endif
	}
	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
};


text:
/* 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;
}


text:
/* 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


text:
#include "tolua_fix.h"
#include <stdlib.h>

static int s_function_ref_id = 0;

TOLUA_API void toluafix_open(lua_State* L)
{
	lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
	lua_newtable(L);
	lua_rawset(L, LUA_REGISTRYINDEX);

	lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
	lua_newtable(L);
	lua_rawset(L, LUA_REGISTRYINDEX);

	lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
	lua_newtable(L);
	lua_rawset(L, LUA_REGISTRYINDEX);
}

#if 0
TOLUA_API int toluafix_pushusertype_ccobject(lua_State* L,
	int refid,
	int* p_refid,
	void* ptr,
	const char* type)
{
	if (ptr == NULL || p_refid == NULL)
	{
		lua_pushnil(L);
		return -1;
	}

	Ref* vPtr = static_cast<Ref*>(ptr);
	const char* vType = getLuaTypeName(vPtr, type);

	if (*p_refid == 0)
	{
		*p_refid = refid;

		lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
		lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: refid_ptr */
		lua_pushinteger(L, refid);                                  /* stack: refid_ptr refid */
		lua_pushlightuserdata(L, vPtr);                              /* stack: refid_ptr refid ptr */

		lua_rawset(L, -3);                  /* refid_ptr[refid] = ptr, stack: refid_ptr */
		lua_pop(L, 1);                                              /* stack: - */

		lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
		lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: refid_type */
		lua_pushinteger(L, refid);                                  /* stack: refid_type refid */
		lua_pushstring(L, vType);                                    /* stack: refid_type refid type */
		lua_rawset(L, -3);                /* refid_type[refid] = type, stack: refid_type */
		lua_pop(L, 1);                                              /* stack: - */

		//printf("[LUA] push CCObject OK - refid: %d, ptr: %x, type: %s\n", *p_refid, (int)ptr, type);
	}

	tolua_pushusertype_and_addtoroot(L, vPtr, vType);

	return 0;
}

TOLUA_API int toluafix_remove_ccobject_by_refid(lua_State* L, int refid)
{
	void* ptr = NULL;
	const char* type = NULL;
	void** ud = NULL;
	if (refid == 0) return -1;

	// get ptr from tolua_refid_ptr_mapping
	lua_pushstring(L, TOLUA_REFID_PTR_MAPPING);
	lua_rawget(L, LUA_REGISTRYINDEX);                               /* stack: refid_ptr */
	lua_pushinteger(L, refid);                                      /* stack: refid_ptr refid */
	lua_rawget(L, -2);                                              /* stack: refid_ptr ptr */
	ptr = lua_touserdata(L, -1);
	lua_pop(L, 1);                                                  /* stack: refid_ptr */
	if (ptr == NULL)
	{
		lua_pop(L, 1);
		// Lua stack has closed, C++ object not in Lua.
		// printf("[LUA ERROR] remove CCObject with NULL ptr, refid: %d\n", refid);
		return -2;
	}

	// remove ptr from tolua_refid_ptr_mapping
	lua_pushinteger(L, refid);                                      /* stack: refid_ptr refid */
	lua_pushnil(L);                                                 /* stack: refid_ptr refid nil */
	lua_rawset(L, -3);                     /* delete refid_ptr[refid], stack: refid_ptr */
	lua_pop(L, 1);                                                  /* stack: - */

	// get type from tolua_refid_type_mapping
	lua_pushstring(L, TOLUA_REFID_TYPE_MAPPING);
	lua_rawget(L, LUA_REGISTRYINDEX);                               /* stack: refid_type */
	lua_pushinteger(L, refid);                                      /* stack: refid_type refid */
	lua_rawget(L, -2);                                              /* stack: refid_type type */
	if (lua_isnil(L, -1))
	{
		lua_pop(L, 2);
		printf("[LUA ERROR] remove CCObject with NULL type, refid: %d, ptr: %p\n", refid, ptr);
		return -1;
	}

	type = lua_tostring(L, -1);
	lua_pop(L, 1);                                                  /* stack: refid_type */

	// remove type from tolua_refid_type_mapping
	lua_pushinteger(L, refid);                                      /* stack: refid_type refid */
	lua_pushnil(L);                                                 /* stack: refid_type refid nil */
	lua_rawset(L, -3);                    /* delete refid_type[refid], stack: refid_type */
	lua_pop(L, 1);                                                  /* stack: - */

	// get ubox
	luaL_getmetatable(L, type);                                     /* stack: mt */
	lua_pushstring(L, "tolua_ubox");                                /* stack: mt key */
	lua_rawget(L, -2);                                              /* stack: mt ubox */
	if (lua_isnil(L, -1))
	{
		// use global ubox
		lua_pop(L, 1);                                              /* stack: mt */
		lua_pushstring(L, "tolua_ubox");                            /* stack: mt key */
		lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: mt ubox */
	};

	// cleanup root
	tolua_remove_value_from_root(L, ptr);

	lua_pushlightuserdata(L, ptr);                                  /* stack: mt ubox ptr */
	lua_rawget(L, -2);                                               /* stack: mt ubox ud */
	if (lua_isnil(L, -1))
	{
		// Lua object has released (GC), C++ object not in ubox.
		//printf("[LUA ERROR] remove CCObject with NULL ubox, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
		lua_pop(L, 3);
		return -3;
	}

	// cleanup peertable
	lua_pushvalue(L, LUA_REGISTRYINDEX);
	lua_setfenv(L, -2);

	ud = (void**)lua_touserdata(L, -1);
	lua_pop(L, 1);                                                  /* stack: mt ubox */
	if (ud == NULL)
	{
		printf("[LUA ERROR] remove CCObject with NULL userdata, refid: %d, ptr: %p, type: %s\n", refid, ptr, type);
		lua_pop(L, 2);
		return -1;
	}

	// clean userdata
	*ud = NULL;

	lua_pushlightuserdata(L, ptr);                                  /* stack: mt ubox ptr */
	lua_pushnil(L);                                                 /* stack: mt ubox ptr nil */
	lua_rawset(L, -3);                             /* ubox[ptr] = nil, stack: mt ubox */

	lua_pop(L, 2);
	//printf("[LUA] remove CCObject, refid: %d, ptr: %x, type: %s\n", refid, (int)ptr, type);
	return 0;
}
#endif

TOLUA_API int toluafix_ref_function(lua_State* L, int lo, int def)
{
	// function at lo
	if (!lua_isfunction(L, lo)) return 0;

	s_function_ref_id++;

	lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
	lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: fun ... refid_fun */
	lua_pushinteger(L, s_function_ref_id);                      /* stack: fun ... refid_fun refid */
	lua_pushvalue(L, lo);                                       /* stack: fun ... refid_fun refid fun */

	lua_rawset(L, -3);                  /* refid_fun[refid] = fun, stack: fun ... refid_ptr */
	lua_pop(L, 1);                                              /* stack: fun ... */

	return s_function_ref_id;

	// lua_pushvalue(L, lo);                                           /* stack: ... func */
	// return luaL_ref(L, LUA_REGISTRYINDEX);
}

TOLUA_API void toluafix_get_function_by_refid(lua_State* L, int refid)
{
	lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
	lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: ... refid_fun */
	lua_pushinteger(L, refid);                                  /* stack: ... refid_fun refid */
	lua_rawget(L, -2);                                          /* stack: ... refid_fun fun */
	lua_remove(L, -2);                                          /* stack: ... fun */
}

TOLUA_API void toluafix_remove_function_by_refid(lua_State* L, int refid)
{
	lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);
	lua_rawget(L, LUA_REGISTRYINDEX);                           /* stack: ... refid_fun */
	lua_pushinteger(L, refid);                                  /* stack: ... refid_fun refid */
	lua_pushnil(L);                                             /* stack: ... refid_fun refid nil */
	lua_rawset(L, -3);                  /* refid_fun[refid] = fun, stack: ... refid_ptr */
	lua_pop(L, 1);                                              /* stack: ... */

	// luaL_unref(L, LUA_REGISTRYINDEX, refid);
}

// check lua value is funciton
TOLUA_API int toluafix_isfunction(lua_State* L, int lo, const char* type, int def, tolua_Error* err)
{
	if (lua_gettop(L) >= abs(lo) && lua_isfunction(L, lo))
	{
		return 1;
	}
	err->index = lo;
	err->array = 0;
	err->type = "[not function]";
	return 0;
}

TOLUA_API int toluafix_totable(lua_State* L, int lo, int def)
{
	return lo;
}

TOLUA_API int toluafix_istable(lua_State* L, int lo, const char* type, int def, tolua_Error* err)
{
	return tolua_istable(L, lo, def, err);
}

TOLUA_API void toluafix_stack_dump(lua_State* L, const char* label)
{
	int i;
	int top = lua_gettop(L);
	printf("Total [%d] in lua stack: %s\n", top, label != 0 ? label : "");
	for (i = -1; i >= -top; i--)
	{
		int t = lua_type(L, i);
		switch (t)
		{
		case LUA_TSTRING:
			printf("  [%02d] string %s\n", i, lua_tostring(L, i));
			break;
		case LUA_TBOOLEAN:
			printf("  [%02d] boolean %s\n", i, lua_toboolean(L, i) ? "true" : "false");
			break;
		case LUA_TNUMBER:
			printf("  [%02d] number %g\n", i, lua_tonumber(L, i));
			break;
		default:
			printf("  [%02d] %s\n", i, lua_typename(L, t));
		}
	}
	printf("\n");
}


text:
/* 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


text:
/* 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


text:
/*
   Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

   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; version 2 of the License.

   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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */

#ifndef _m_string_h
#define _m_string_h

#include "my_global.h"                          /* HAVE_* */

#include <string.h>

#define bfill please_use_memset_rather_than_bfill
#define bzero please_use_memset_rather_than_bzero
#define bmove please_use_memmove_rather_than_bmove
#define strmov please_use_my_stpcpy_or_my_stpmov_rather_than_strmov
#define strnmov please_use_my_stpncpy_or_my_stpnmov_rather_than_strnmov

#include "mysql/service_my_snprintf.h"

#if defined(__cplusplus)
extern "C" {
#endif

/*
  my_str_malloc(), my_str_realloc() and my_str_free() are assigned to
  implementations in strings/alloc.c, but can be overridden in
  the calling program.
 */
extern void *(*my_str_malloc)(size_t);
extern void *(*my_str_realloc)(void *, size_t);
extern void (*my_str_free)(void *);

/* Declared in int2str() */
extern char _dig_vec_upper[];
extern char _dig_vec_lower[];

	/* Prototypes for string functions */

extern	void bchange(uchar *dst,size_t old_len,const uchar *src,
		     size_t new_len,size_t tot_len);
extern	void strappend(char *s,size_t len,pchar fill);
extern	char *strend(const char *s);
extern  char *strcend(const char *, pchar);
extern	char *strfill(char * s,size_t len,pchar fill);
extern	char *strmake(char *dst,const char *src,size_t length);

extern	char *my_stpmov(char *dst,const char *src);
extern	char *my_stpnmov(char *dst, const char *src, size_t n);
extern	char *strcont(const char *src, const char *set);
extern	char *strxmov(char *dst, const char *src, ...);
extern	char *strxnmov(char *dst, size_t len, const char *src, ...);

/**
   Copy a string from src to dst until (and including) terminating null byte.

   @param dst   Destination
   @param src   Source

   @note src and dst cannot overlap.
         Use my_stpmov() if src and dst overlaps.

   @note Unsafe, consider using my_stpnpy() instead.

   @return pointer to terminating null byte.
*/
static inline char *my_stpcpy(char *dst, const char *src)
{
#if defined(HAVE_BUILTIN_STPCPY)
  return __builtin_stpcpy(dst, src);
#elif defined(HAVE_STPCPY)
  return stpcpy(dst, src);
#else
  /* Fallback to implementation supporting overlap. */
  return my_stpmov(dst, src);
#endif
}

/**
   Copy fixed-size string from src to dst.

   @param dst   Destination
   @param src   Source
   @param n     Maximum number of characters to copy.

   @note src and dst cannot overlap
         Use my_stpnmov() if src and dst overlaps.

   @return pointer to terminating null byte.
*/
static inline char *my_stpncpy(char *dst, const char *src, size_t n)
{
#if defined(HAVE_STPNCPY)
  return stpncpy(dst, src, n);
#else
  /* Fallback to implementation supporting overlap. */
  return my_stpnmov(dst, src, n);
#endif
}

static inline longlong my_strtoll(const char *nptr, char **endptr, int base)
{
#if defined _WIN32
  return _strtoi64(nptr, endptr, base);
#else
  return strtoll(nptr, endptr, base);
#endif
}

static inline ulonglong my_strtoull(const char *nptr, char **endptr, int base)
{
#if defined _WIN32
  return _strtoui64(nptr, endptr, base);
#else
  return strtoull(nptr, endptr, base);
#endif
}

static inline char *my_strtok_r(char *str, const char *delim, char **saveptr)
{
#if defined _WIN32
  return strtok_s(str, delim, saveptr);
#else
  return strtok_r(str, delim, saveptr);
#endif
}

/* native_ rather than my_ since my_strcasecmp already exists */
static inline int native_strcasecmp(const char *s1, const char *s2)
{
#if defined _WIN32
  return _stricmp(s1, s2);
#else
  return strcasecmp(s1, s2);
#endif
}

/* native_ rather than my_ for consistency with native_strcasecmp */
static inline int native_strncasecmp(const char *s1, const char *s2, size_t n)
{
#if defined _WIN32
  return _strnicmp(s1, s2, n);
#else
  return strncasecmp(s1, s2, n);
#endif
}

size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);

/* Prototypes of normal stringfunctions (with may ours) */
#ifndef HAVE_STRNLEN
extern size_t strnlen(const char *s, size_t n);
#endif

extern int is_prefix(const char *, const char *);

/* Conversion routines */
typedef enum {
  MY_GCVT_ARG_FLOAT,
  MY_GCVT_ARG_DOUBLE
} my_gcvt_arg_type;

double my_strtod(const char *str, char **end, int *error);
double my_atof(const char *nptr);
size_t my_fcvt(double x, int precision, char *to, my_bool *error);
size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to,
               my_bool *error);

#define NOT_FIXED_DEC 31

/*
  The longest string my_fcvt can return is 311 + "precision" bytes.
  Here we assume that we never cal my_fcvt() with precision >= NOT_FIXED_DEC
  (+ 1 byte for the terminating '\0').
*/
#define FLOATING_POINT_BUFFER (311 + NOT_FIXED_DEC)

/*
  We want to use the 'e' format in some cases even if we have enough space
  for the 'f' one just to mimic sprintf("%.15g") behavior for large integers,
  and to improve it for numbers < 10^(-4).
  That is, for |x| < 1 we require |x| >= 10^(-15), and for |x| > 1 we require
  it to be integer and be <= 10^DBL_DIG for the 'f' format to be used.
  We don't lose precision, but make cases like "1e200" or "0.00001" look nicer.
*/
#define MAX_DECPT_FOR_F_FORMAT DBL_DIG

/*
  The maximum possible field width for my_gcvt() conversion.
  (DBL_DIG + 2) significant digits + sign + "." + ("e-NNN" or
  MAX_DECPT_FOR_F_FORMAT zeros for cases when |x|<1 and the 'f' format is used).
*/
#define MY_GCVT_MAX_FIELD_WIDTH (DBL_DIG + 4 + MY_MAX(5, MAX_DECPT_FOR_F_FORMAT)) \

extern char *llstr(longlong value,char *buff);
extern char *ullstr(longlong value,char *buff);

extern char *int2str(long val, char *dst, int radix, int upcase);
extern char *int10_to_str(long val,char *dst,int radix);
extern char *str2int(const char *src,int radix,long lower,long upper,
			 long *val);
longlong my_strtoll10(const char *nptr, char **endptr, int *error);
#if SIZEOF_LONG == SIZEOF_LONG_LONG
#define ll2str(A,B,C,D) int2str((A),(B),(C),(D))
#define longlong10_to_str(A,B,C) int10_to_str((A),(B),(C))
#undef strtoll
#define strtoll(A,B,C) strtol((A),(B),(C))
#define strtoull(A,B,C) strtoul((A),(B),(C))
#else
extern char *ll2str(longlong val,char *dst,int radix, int upcase);
extern char *longlong10_to_str(longlong val,char *dst,int radix);
#endif
#define longlong2str(A,B,C) ll2str((A),(B),(C),1)

#if defined(__cplusplus)
}
#endif

/*
  LEX_STRING -- a pair of a C-string and its length.
  (it's part of the plugin API as a MYSQL_LEX_STRING)
  Ditto LEX_CSTRING/MYSQL_LEX_CSTRING.
*/

#include <mysql/mysql_lex_string.h>
typedef struct st_mysql_lex_string LEX_STRING;
typedef struct st_mysql_const_lex_string LEX_CSTRING;

#define STRING_WITH_LEN(X) (X), ((sizeof(X) - 1))
#define USTRING_WITH_LEN(X) ((uchar*) X), ((sizeof(X) - 1))
#define C_STRING_WITH_LEN(X) ((char *) (X)), ((sizeof(X) - 1))

/**
  Skip trailing space.

  On most systems reading memory in larger chunks (ideally equal to the size of
  the chinks that the machine physically reads from memory) causes fewer memory
  access loops and hence increased performance.
  This is why the 'int' type is used : it's closest to that (according to how
  it's defined in C).
  So when we determine the amount of whitespace at the end of a string we do
  the following :
    1. We divide the string into 3 zones :
      a) from the start of the string (__start) to the first multiple
        of sizeof(int)  (__start_words)
      b) from the end of the string (__end) to the last multiple of sizeof(int)
        (__end_words)
      c) a zone that is aligned to sizeof(int) and can be safely accessed
        through an int *
    2. We start comparing backwards from (c) char-by-char. If all we find is
       space then we continue
    3. If there are elements in zone (b) we compare them as unsigned ints to a
       int mask (SPACE_INT) consisting of all spaces
    4. Finally we compare the remaining part (a) of the string char by char.
       This covers for the last non-space unsigned int from 3. (if any)

   This algorithm works well for relatively larger strings, but it will slow
   the things down for smaller strings (because of the additional calculations
   and checks compared to the naive method). Thus the barrier of length 20
   is added.

   @param     ptr   pointer to the input string
   @param     len   the length of the string
   @return          the last non-space character
*/
#if defined(__sparc) || defined(__sparcv9)
static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len)
{
  /* SPACE_INT is a word that contains only spaces */
#if SIZEOF_INT == 4
  const unsigned SPACE_INT= 0x20202020U;
#elif SIZEOF_INT == 8
  const unsigned SPACE_INT= 0x2020202020202020ULL;
#else
#error define the appropriate constant for a word full of spaces
#endif

  const uchar *end= ptr + len;

  if (len > 20)
  {
    const uchar *end_words= (const uchar *)(intptr)
      (((ulonglong)(intptr)end) / SIZEOF_INT * SIZEOF_INT);
    const uchar *start_words= (const uchar *)(intptr)
       ((((ulonglong)(intptr)ptr) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT);

    DBUG_ASSERT(end_words > ptr);
    while (end > end_words && end[-1] == 0x20)
      end--;
    if (end[-1] == 0x20 && start_words < end_words)
      while (end > start_words && ((unsigned *)end)[-1] == SPACE_INT)
        end -= SIZEOF_INT;
  }
  while (end > ptr && end[-1] == 0x20)
    end--;
  return (end);
}
#else
/*
  Reads 8 bytes at a time, ignoring alignment.
  We use uint8korr, which is fast (it simply reads a *ulonglong)
  on all platforms, except sparc.
*/
static inline const uchar *skip_trailing_space(const uchar *ptr, size_t len)
{
  const uchar *end= ptr + len;
  while (end - ptr >= 8)
  {
    if (uint8korr(end-8) != 0x2020202020202020ULL)
      break;
    end-= 8;
  }
  while (end > ptr && end[-1] == 0x20)
    end--;
  return (end);
}
#endif

static inline void lex_string_set(LEX_STRING *lex_str, const char *c_str)
{
  lex_str->str= (char *) c_str;
  lex_str->length= strlen(c_str);
}

static inline void lex_cstring_set(LEX_CSTRING *lex_str, const char *c_str)
{
  lex_str->str= c_str;
  lex_str->length= strlen(c_str);
}

#endif


text:
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

   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; version 2 of the License.

   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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */

#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)

#ifndef MYSQL_CLIENT
#error This header is supposed to be used only in the client
#endif

    case OPT_SSL_MODE:
      opt_ssl_mode= find_type_or_exit(argument, &ssl_mode_typelib,
                                      opt->name);
      ssl_mode_set_explicitly= TRUE;
      break;
    case OPT_SSL_SSL:
      CLIENT_WARN_DEPRECATED("--ssl", "--ssl-mode");
      if (!opt_use_ssl_arg)
        opt_ssl_mode= SSL_MODE_DISABLED;
      else if (opt_ssl_mode < SSL_MODE_REQUIRED)
        opt_ssl_mode= SSL_MODE_REQUIRED;
      break;
    case OPT_SSL_VERIFY_SERVER_CERT:
      CLIENT_WARN_DEPRECATED("--ssl-verify-server-cert",
                             "--ssl-mode=VERIFY_IDENTITY");
      if (!opt_ssl_verify_server_cert_arg)
      {
        if (opt_ssl_mode >= SSL_MODE_VERIFY_IDENTITY)
          opt_ssl_mode= SSL_MODE_VERIFY_CA;
      }
      else
        opt_ssl_mode= SSL_MODE_VERIFY_IDENTITY;
      break;
    case OPT_SSL_CA:
    case OPT_SSL_CAPATH:
      /* Don't change ssl-mode if set explicitly. */
      if (!ssl_mode_set_explicitly)
        opt_ssl_mode= SSL_MODE_VERIFY_CA;
      break;
    case OPT_SSL_KEY:
    case OPT_SSL_CERT:
    case OPT_SSL_CIPHER:
    case OPT_SSL_CRL:
    case OPT_SSL_CRLPATH:
    case OPT_TLS_VERSION:
#ifdef HAVE_YASSL
      /* crl has no effect in yaSSL. */
      opt_ssl_crl= NULL;
      opt_ssl_crlpath= NULL;
#endif /* HAVE_YASSL */
      break;
#endif /* HAVE_OPENSSL */