Ejemplo n.º 1
0
lua_t*
lua_allocate(void) {
	lua_t* env = memory_allocate(HASH_LUA, sizeof(lua_t), 0,
	                             MEMORY_PERSISTENT | MEMORY_32BIT_ADDRESS | MEMORY_ZERO_INITIALIZED);

	//Foundation allocators can meet demands of luajit on both 32 and 64 bit platforms
	lua_State* state = lua_newstate(lua_allocator, env);
	if (!state) {
		log_error(HASH_LUA, ERROR_INTERNAL_FAILURE, STRING_CONST("Unable to allocate Lua state"));
		memory_deallocate(env);
		return 0;
	}

	lua_atpanic(state, lua_panic);

	//Disable automagic gc
	lua_gc(state, LUA_GCCOLLECT, 0);

	lua_pushlightuserdata(state, env);
	lua_setlglobal(state, "__environment", 13);

	env->state = state;
	env->calldepth = 0;

#if BUILD_ENABLE_LUA_THREAD_SAFE
	semaphore_initialize(&env->execution_right, 1);
	env->queue_head = 0;
	atomic_store32(&env->queue_tail, 0);
#endif

	int stacksize = lua_gettop(state);

	luaL_openlibs(state);

	lua_module_registry_initialize(state);

	lua_pop(state, lua_gettop(state) - stacksize);

	return env;
}
Ejemplo n.º 2
0
static void
lua_push_method_global(lua_State* state, const char* name, size_t length, lua_CFunction fn) {
	lua_pushcclosure(state, fn, 0);
	lua_setlglobal(state, name, length);
}
Ejemplo n.º 3
0
static void
lua_push_integer_global(lua_State* state, const char* name, size_t length, int value) {
	lua_pushinteger(state, value);
	lua_setlglobal(state, name, length);
}
Ejemplo n.º 4
0
static void
lua_push_number_global(lua_State* state, const char* name, size_t length, real value) {
	lua_pushnumber(state, value);
	lua_setlglobal(state, name, length);
}
Ejemplo n.º 5
0
lua_result_t
lua_do_bind(lua_t* env, const char* property, size_t length, lua_command_t cmd, lua_value_t val) {
	lua_State* state;
	int stacksize;
	size_t start, next;
	string_const_t part;

	if (!env || !length)
		return LUA_ERROR;

	state = env->state;
	stacksize = lua_gettop(state);

	next = string_find(property, length, '.', 0);
	if (next != STRING_NPOS) {
		int tables;
		unsigned int numtables = 0;
		part = string_const(property, next);

		lua_getlglobal(state, part.str, part.length);
		if (lua_isnil(state, -1)) {
			//Create global table
			lua_pop(state, 1);
			lua_newtable(state);
			lua_pushvalue(state, -1);
			lua_setlglobal(state, part.str, part.length);
			log_debugf(HASH_LUA, STRING_CONST("Created global table: %.*s"), STRING_FORMAT(part));
		}
		else if (!lua_istable(state, -1)) {
			log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
			           STRING_CONST("Invalid script bind call, existing data '%.*s' in '%.*s' is not a table"),
			           STRING_FORMAT(part), (int)length, property);
			lua_pop(state, lua_gettop(state) - stacksize);
			return LUA_ERROR;
		}
		//Top of stack is now table
		FOUNDATION_ASSERT(lua_istable(state, -1));

		++next;
		start = next;
		++numtables;

		next = string_find(property, length, '.', next);
		while (next != STRING_NPOS) {
			part = string_const(property + start, next - start);
			lua_pushlstring(state, part.str, part.length);
			lua_gettable(state, -2);
			if (lua_isnil(state, -1)) {
				//Create sub-table
				lua_pop(state, 1);
				lua_newtable(state);
				lua_pushlstring(state, part.str, part.length);
				lua_pushvalue(state, -2);
				lua_settable(state, -4);
				log_debugf(HASH_LUA, STRING_CONST("Created table: %.*s"), next, property);
			}
			else if (!lua_istable(state, -1)) {
				log_errorf(HASH_LUA, ERROR_INVALID_VALUE,
				           STRING_CONST("Invalid script bind call, existing data '%.*s' in '%.*s' is not a table"),
				           STRING_FORMAT(part), (int)next, property);
				lua_pop(state, lua_gettop(state) - stacksize);
				return LUA_ERROR;
			}
			//Top of stack is now table
			FOUNDATION_ASSERT(lua_istable(state, -1));

			++next;
			start = next;
			next = string_find(property, length, '.', next);
			++numtables;
		}

		part = string_const(property + start, length - start);

		switch (cmd) {
		case LUACMD_BIND:
			lua_push_method(state, STRING_ARGS(part), val.fn);
			break;
		case LUACMD_BIND_INT:
			lua_push_integer(state, STRING_ARGS(part), val.ival);
			break;
		case LUACMD_BIND_VAL:
			lua_push_number(state, STRING_ARGS(part), val.val);
			break;
		default:
			break;
		}

		tables = lua_gettop(state) - stacksize;
		lua_pop(state, tables);

		FOUNDATION_ASSERT(tables == (int)numtables);
	}
	else {
		part = string_const(property, length);
		switch (cmd) {
		case LUACMD_BIND:
			lua_push_method_global(state, STRING_ARGS(part), val.fn);
			break;
		case LUACMD_BIND_INT:
			lua_push_integer_global(state, STRING_ARGS(part), val.ival);
			break;
		case LUACMD_BIND_VAL:
			lua_push_number_global(state, STRING_ARGS(part), val.val);
			break;
		default:
			break;
		}
	}
	return LUA_OK;
}