Example #1
0
int main() {

	L = luaL_newstate();
	luaL_openlibs(L);
	luaL_requiref(L, "love", initLove, 1);

	sf2d_init(); // 2D Drawing lib.
	sftd_init(); // Text Drawing lib.
	cfguInit();
	ptmuInit();

	// consoleInit(GFX_BOTTOM, NULL);

	sf2d_set_clear_color(RGBA8(0x0, 0x0, 0x0, 0xFF)); // Reset background color.

	osSetSpeedupEnable(true); // Enables CPU speedup for a free performance boost.

	// Detect if we are running on a .cia, because if we are
	// we load from RomFS rather than the SD Card.
	// TODO: Load RomFS from .3dsx's aswell.

	Result rc = romfsInit();

	romfsExists = (rc) ? false : true;

	// Change working directory

	if (romfsExists) {

		chdir("romfs:/");

	} else {

		char cwd[256];
		getcwd(cwd, 256);
		char newCwd[261];

		strcat(newCwd, cwd);
		strcat(newCwd, "game");
		chdir(newCwd);

	}

	luaL_dobuffer(L, boot_lua, boot_lua_size, "boot"); // Do some setup Lua side.

	// If main.lua exists, execute it.
	// If not then just load the nogame screen.

	if (fileExists("main.lua")) {
		if (luaL_dofile(L, "main.lua")) displayError();
	} else {
		if (luaL_dobuffer(L, nogame_lua, nogame_lua_size, "nogame")) displayError();
	}
	
	if (luaL_dostring(L, "love.timer.step()")) displayError();

	if (luaL_dostring(L, "if love.load then love.load() end")) displayError();

	while (aptMainLoop()) {

		if (shouldQuit) {

			if (forceQuit) break;

			bool shouldAbort = false;

			// lua_getfield(L, LUA_GLOBALSINDEX, "love");
			// lua_getfield(L, -1, "quit");
			// lua_remove(L, -2);

			// if (!lua_isnil(L, -1)) {

			// 	lua_call(L, 0, 1);
			// 	shouldAbort = lua_toboolean(L, 1);
			// 	lua_pop(L, 1);

			// }; TODO: Do this properly.

			if (luaL_dostring(L, "if love.quit then love.quit() end")) displayError();

			if (!shouldAbort && !errorOccured) break;

		} // Quit event

		if (!errorOccured) {

			if (luaL_dostring(L,
				"love.keyboard.scan()\n"
				"love.timer.step()\n"
				"if love.update then love.update(love.timer.getDelta()) end")) {
					displayError();
			}

			// Top screen
			// Left side

			sf2d_start_frame(GFX_TOP, GFX_LEFT);

				if (luaL_dostring(L, "if love.draw then love.draw() end")) displayError();

			sf2d_end_frame();

			// Right side

			if (is3D) {

				sf2d_start_frame(GFX_TOP, GFX_RIGHT);

					if (luaL_dostring(L, "if love.draw then love.draw() end")) displayError();

				sf2d_end_frame();

			}

			// Bot screen

			sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);

				if (luaL_dostring(L, "if love.draw then love.draw() end")) displayError();

			sf2d_end_frame();

			luaL_dostring(L, "love.graphics.present()");

		} else {

			hidScanInput();
			u32 kTempDown = hidKeysDown();
			if (kTempDown & KEY_START) {
				forceQuit = true;
				shouldQuit = true;
			}

			char *errMsg = lua_tostring(L, -1);

			sf2d_start_frame(GFX_TOP, GFX_LEFT);

				lua_getfield(L, LUA_GLOBALSINDEX, "love");
				lua_getfield(L, -1, "errhand");
				lua_remove(L, -2);

				if (!lua_isnil(L, -1)) {

					lua_pushstring(L, errMsg);
					lua_call(L, 1, 0);

				}

			sf2d_end_frame();

			sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);

				lua_getfield(L, LUA_GLOBALSINDEX, "love");
				lua_getfield(L, -1, "errhand");
				lua_remove(L, -2);

				if (!lua_isnil(L, -1)) {

					lua_pushstring(L, errMsg);
					lua_call(L, 1, 0);

				}

			sf2d_end_frame();

			luaL_dostring(L, "love.graphics.present()");

		}

	}

	luaL_dostring(L, "love.audio.stop()");

	lua_close(L);

	sftd_fini();
	sf2d_fini();
	cfguExit();
	ptmuExit();

	if (soundEnabled) ndspExit();
	if (romfsExists) romfsExit();

	return 0;

}
Example #2
0
ContentFeatures read_content_features(lua_State *L, int index)
{
	if(index < 0)
		index = lua_gettop(L) + 1 + index;

	ContentFeatures f;

	/* Cache existence of some callbacks */
	lua_getfield(L, index, "on_construct");
	if(!lua_isnil(L, -1)) f.has_on_construct = true;
	lua_pop(L, 1);
	lua_getfield(L, index, "on_destruct");
	if(!lua_isnil(L, -1)) f.has_on_destruct = true;
	lua_pop(L, 1);
	lua_getfield(L, index, "after_destruct");
	if(!lua_isnil(L, -1)) f.has_after_destruct = true;
	lua_pop(L, 1);

	lua_getfield(L, index, "on_rightclick");
	f.rightclickable = lua_isfunction(L, -1);
	lua_pop(L, 1);

	/* Name */
	getstringfield(L, index, "name", f.name);

	/* Groups */
	lua_getfield(L, index, "groups");
	read_groups(L, -1, f.groups);
	lua_pop(L, 1);

	/* Visual definition */

	f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype",
			ScriptApiNode::es_DrawType,NDT_NORMAL);
	getfloatfield(L, index, "visual_scale", f.visual_scale);

	/* Meshnode model filename */
	getstringfield(L, index, "mesh", f.mesh);

	// tiles = {}
	lua_getfield(L, index, "tiles");
	// If nil, try the deprecated name "tile_images" instead
	if(lua_isnil(L, -1)){
		lua_pop(L, 1);
		warn_if_field_exists(L, index, "tile_images",
				"Deprecated; new name is \"tiles\".");
		lua_getfield(L, index, "tile_images");
	}
	if(lua_istable(L, -1)){
		int table = lua_gettop(L);
		lua_pushnil(L);
		int i = 0;
		while(lua_next(L, table) != 0){
			// Read tiledef from value
			f.tiledef[i] = read_tiledef(L, -1);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
			i++;
			if(i==6){
				lua_pop(L, 1);
				break;
			}
		}
		// Copy last value to all remaining textures
		if(i >= 1){
			TileDef lasttile = f.tiledef[i-1];
			while(i < 6){
				f.tiledef[i] = lasttile;
				i++;
			}
		}
	}
	lua_pop(L, 1);

	// special_tiles = {}
	lua_getfield(L, index, "special_tiles");
	// If nil, try the deprecated name "special_materials" instead
	if(lua_isnil(L, -1)){
		lua_pop(L, 1);
		warn_if_field_exists(L, index, "special_materials",
				"Deprecated; new name is \"special_tiles\".");
		lua_getfield(L, index, "special_materials");
	}
	if(lua_istable(L, -1)){
		int table = lua_gettop(L);
		lua_pushnil(L);
		int i = 0;
		while(lua_next(L, table) != 0){
			// Read tiledef from value
			f.tiledef_special[i] = read_tiledef(L, -1);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
			i++;
			if(i==CF_SPECIAL_COUNT){
				lua_pop(L, 1);
				break;
			}
		}
	}
	lua_pop(L, 1);

	f.alpha = getintfield_default(L, index, "alpha", 255);

	bool usealpha = getboolfield_default(L, index,
			"use_texture_alpha", false);
	if (usealpha)
		f.alpha = 0;

	/* Other stuff */

	lua_getfield(L, index, "post_effect_color");
	read_color(L, -1, &f.post_effect_color);
	lua_pop(L, 1);

	f.param_type = (ContentParamType)getenumfield(L, index, "paramtype",
			ScriptApiNode::es_ContentParamType, CPT_NONE);
	f.param_type_2 = (ContentParamType2)getenumfield(L, index, "paramtype2",
			ScriptApiNode::es_ContentParamType2, CPT2_NONE);

	// Warn about some deprecated fields
	warn_if_field_exists(L, index, "wall_mounted",
			"deprecated: use paramtype2 = 'wallmounted'");
	warn_if_field_exists(L, index, "light_propagates",
			"deprecated: determined from paramtype");
	warn_if_field_exists(L, index, "dug_item",
			"deprecated: use 'drop' field");
	warn_if_field_exists(L, index, "extra_dug_item",
			"deprecated: use 'drop' field");
	warn_if_field_exists(L, index, "extra_dug_item_rarity",
			"deprecated: use 'drop' field");
	warn_if_field_exists(L, index, "metadata_name",
			"deprecated: use on_add and metadata callbacks");

	// True for all ground-like things like stone and mud, false for eg. trees
	getboolfield(L, index, "is_ground_content", f.is_ground_content);
	f.light_propagates = (f.param_type == CPT_LIGHT);
	getboolfield(L, index, "sunlight_propagates", f.sunlight_propagates);
	// This is used for collision detection.
	// Also for general solidness queries.
	getboolfield(L, index, "walkable", f.walkable);
	// Player can point to these
	getboolfield(L, index, "pointable", f.pointable);
	// Player can dig these
	getboolfield(L, index, "diggable", f.diggable);
	// Player can climb these
	getboolfield(L, index, "climbable", f.climbable);
	// Player can build on these
	getboolfield(L, index, "buildable_to", f.buildable_to);
	// Whether the node is non-liquid, source liquid or flowing liquid
	f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
			ScriptApiNode::es_LiquidType, LIQUID_NONE);
	// If the content is liquid, this is the flowing version of the liquid.
	getstringfield(L, index, "liquid_alternative_flowing",
			f.liquid_alternative_flowing);
	// If the content is liquid, this is the source version of the liquid.
	getstringfield(L, index, "liquid_alternative_source",
			f.liquid_alternative_source);
	// Viscosity for fluid flow, ranging from 1 to 7, with
	// 1 giving almost instantaneous propagation and 7 being
	// the slowest possible
	f.liquid_viscosity = getintfield_default(L, index,
			"liquid_viscosity", f.liquid_viscosity);
	f.liquid_range = getintfield_default(L, index,
			"liquid_range", f.liquid_range);
	f.leveled = getintfield_default(L, index, "leveled", f.leveled);

	getboolfield(L, index, "liquid_renewable", f.liquid_renewable);
	f.drowning = getintfield_default(L, index,
			"drowning", f.drowning);
	// Amount of light the node emits
	f.light_source = getintfield_default(L, index,
			"light_source", f.light_source);
	f.damage_per_second = getintfield_default(L, index,
			"damage_per_second", f.damage_per_second);

	lua_getfield(L, index, "node_box");
	if(lua_istable(L, -1))
		f.node_box = read_nodebox(L, -1);
	lua_pop(L, 1);

	lua_getfield(L, index, "selection_box");
	if(lua_istable(L, -1))
		f.selection_box = read_nodebox(L, -1);
 	lua_pop(L, 1);

	lua_getfield(L, index, "collision_box");
	if(lua_istable(L, -1))
		f.collision_box = read_nodebox(L, -1);
	lua_pop(L, 1);

	f.waving = getintfield_default(L, index,
			"waving", f.waving);

	// Set to true if paramtype used to be 'facedir_simple'
	getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
	// Set to true if wall_mounted used to be set to true
	getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);

	// Sound table
	lua_getfield(L, index, "sounds");
	if(lua_istable(L, -1)){
		lua_getfield(L, -1, "footstep");
		read_soundspec(L, -1, f.sound_footstep);
		lua_pop(L, 1);
		lua_getfield(L, -1, "dig");
		read_soundspec(L, -1, f.sound_dig);
		lua_pop(L, 1);
		lua_getfield(L, -1, "dug");
		read_soundspec(L, -1, f.sound_dug);
		lua_pop(L, 1);
	}
	lua_pop(L, 1);

	return f;
}
Example #3
0
void evalGenericCommand(redisClient *c, int evalsha) {
    lua_State *lua = server.lua;
    char funcname[43];
    long long numkeys;
    int delhook = 0, err;

    /* We want the same PRNG sequence at every call so that our PRNG is
     * not affected by external state. */
    redisSrand48(0);

    /* We set this flag to zero to remember that so far no random command
     * was called. This way we can allow the user to call commands like
     * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command
     * is called (otherwise the replication and AOF would end with non
     * deterministic sequences).
     *
     * Thanks to this flag we'll raise an error every time a write command
     * is called after a random command was used. */
    server.lua_random_dirty = 0;
    server.lua_write_dirty = 0;

    /* Get the number of arguments that are keys */
    if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK)
        return;
    if (numkeys > (c->argc - 3)) {
        addReplyError(c,"Number of keys can't be greater than number of args");
        return;
    }

    /* We obtain the script SHA1, then check if this function is already
     * defined into the Lua state */
    funcname[0] = 'f';
    funcname[1] = '_';
    if (!evalsha) {
        /* Hash the code if this is an EVAL call */
        sha1hex(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr));
    } else {
        /* We already have the SHA if it is a EVALSHA */
        int j;
        char *sha = c->argv[1]->ptr;

        /* Convert to lowercase. We don't use tolower since the function
         * managed to always show up in the profiler output consuming
         * a non trivial amount of time. */
        for (j = 0; j < 40; j++)
            funcname[j+2] = (sha[j] >= 'A' && sha[j] <= 'Z') ?
                sha[j]+('a'-'A') : sha[j];
        funcname[42] = '\0';
    }

    /* Push the pcall error handler function on the stack. */
    lua_getglobal(lua, "__redis__err__handler");

    /* Try to lookup the Lua function */
    lua_getglobal(lua, funcname);
    if (lua_isnil(lua,-1)) {
        lua_pop(lua,1); /* remove the nil from the stack */
        /* Function not defined... let's define it if we have the
         * body of the function. If this is an EVALSHA call we can just
         * return an error. */
        if (evalsha) {
            lua_pop(lua,1); /* remove the error handler from the stack. */
            addReply(c, shared.noscripterr);
            return;
        }
        if (luaCreateFunction(c,lua,funcname,c->argv[1]) == REDIS_ERR) {
            lua_pop(lua,1); /* remove the error handler from the stack. */
            /* The error is sent to the client by luaCreateFunction()
             * itself when it returns REDIS_ERR. */
            return;
        }
        /* Now the following is guaranteed to return non nil */
        lua_getglobal(lua, funcname);
        redisAssert(!lua_isnil(lua,-1));
    }

    /* Populate the argv and keys table accordingly to the arguments that
     * EVAL received. */
    luaSetGlobalArray(lua,"KEYS",c->argv+3,(int)numkeys);
    luaSetGlobalArray(lua,"ARGV",c->argv+3+numkeys,(int)(c->argc-3-numkeys));

    /* Select the right DB in the context of the Lua client */
    selectDb(server.lua_client,c->db->id);

    /* Set a hook in order to be able to stop the script execution if it
     * is running for too much time.
     * We set the hook only if the time limit is enabled as the hook will
     * make the Lua script execution slower. */
    server.lua_caller = c;
    server.lua_time_start = mstime();
    server.lua_kill = 0;
    if (server.lua_time_limit > 0 && server.masterhost == NULL) {
        lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000);
        delhook = 1;
    }

    /* At this point whether this script was never seen before or if it was
     * already defined, we can call it. We have zero arguments and expect
     * a single return value. */
    err = lua_pcall(lua,0,1,-2);

    /* Perform some cleanup that we need to do both on error and success. */
    if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */
    if (server.lua_timedout) {
        server.lua_timedout = 0;
        /* Restore the readable handler that was unregistered when the
         * script timeout was detected. */
        aeCreateFileEvent(server.el,c->fd,AE_READABLE,
                          readQueryFromClient,c);
    }
    server.lua_caller = NULL;

    /* Call the Lua garbage collector from time to time to avoid a
     * full cycle performed by Lua, which adds too latency.
     *
     * The call is performed every LUA_GC_CYCLE_PERIOD executed commands
     * (and for LUA_GC_CYCLE_PERIOD collection steps) because calling it
     * for every command uses too much CPU. */
    #define LUA_GC_CYCLE_PERIOD 50
    {
        static long gc_count = 0;

        gc_count++;
        if (gc_count == LUA_GC_CYCLE_PERIOD) {
            lua_gc(lua,LUA_GCSTEP,LUA_GC_CYCLE_PERIOD);
            gc_count = 0;
        }
    }

    if (err) {
        addReplyErrorFormat(c,"Error running script (call to %s): %s\n",
            funcname, lua_tostring(lua,-1));
        lua_pop(lua,2); /* Consume the Lua reply and remove error handler. */
    } else {
        /* On success convert the Lua return value into Redis protocol, and
         * send it to * the client. */
        luaReplyToRedisReply(c,lua); /* Convert and consume the reply. */
        lua_pop(lua,1); /* Remove the error handler. */
    }

    /* EVALSHA should be propagated to Slave and AOF file as full EVAL, unless
     * we are sure that the script was already in the context of all the
     * attached slaves *and* the current AOF file if enabled.
     *
     * To do so we use a cache of SHA1s of scripts that we already propagated
     * as full EVAL, that's called the Replication Script Cache.
     *
     * For repliation, everytime a new slave attaches to the master, we need to
     * flush our cache of scripts that can be replicated as EVALSHA, while
     * for AOF we need to do so every time we rewrite the AOF file. */
    if (evalsha) {
        if (!replicationScriptCacheExists(c->argv[1]->ptr)) {
            /* This script is not in our script cache, replicate it as
             * EVAL, then add it into the script cache, as from now on
             * slaves and AOF know about it. */
            robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr);

            replicationScriptCacheAdd(c->argv[1]->ptr);
            redisAssertWithInfo(c,NULL,script != NULL);
            rewriteClientCommandArgument(c,0,
                resetRefCount(createStringObject("EVAL",4)));
            rewriteClientCommandArgument(c,1,script);
            forceCommandPropagation(c,REDIS_PROPAGATE_REPL|REDIS_PROPAGATE_AOF);
        }
    }
}
Example #4
0
/*
| Allows user scripts to observe filedescriptors
|
| Params on Lua stack:
|     1: file descriptor
|     2: function to call when read  becomes ready
|     3: function to call when write becomes ready
*/
static int
l_observe_fd( lua_State *L )
{
	int fd = luaL_checknumber( L, 1 );
	bool ready  = false;
	bool writey = false;

	// Stores the user function in the lua registry.
	// It uses the address of the cores ready/write functions
	// for the user as key
	if( !lua_isnoneornil( L, 2 ) )
	{
		lua_pushlightuserdata( L, (void *) user_obs_ready );

		lua_gettable( L, LUA_REGISTRYINDEX );

		if( lua_isnil( L, -1 ) )
		{
			lua_pop               ( L, 1                       );
			lua_newtable          ( L                          );
			lua_pushlightuserdata ( L, (void *) user_obs_ready );
			lua_pushvalue         ( L, -2                      );
			lua_settable          ( L, LUA_REGISTRYINDEX       );
		}

		lua_pushnumber ( L, fd );
		lua_pushvalue  ( L,  2 );
		lua_settable   ( L, -3 );
		lua_pop        ( L,  1 );

		ready = true;
	}

	if( !lua_isnoneornil( L, 3 ) )
	{
		lua_pushlightuserdata( L, (void *) user_obs_writey );

		lua_gettable (L, LUA_REGISTRYINDEX );

		if( lua_isnil(L, -1) )
		{
			lua_pop               ( L, 1                        );
			lua_newtable          ( L                           );
			lua_pushlightuserdata ( L, (void *) user_obs_writey );
			lua_pushvalue         ( L, -2                       );
			lua_settable          ( L, LUA_REGISTRYINDEX        );
		}

		lua_pushnumber ( L, fd );
		lua_pushvalue  ( L,  3 );
		lua_settable   ( L, -3 );
		lua_pop        ( L,  1 );

		writey = true;
	}

	// tells the core to watch the fd
	observe_fd(
		fd,
		ready  ? user_obs_ready : NULL,
		writey ? user_obs_writey : NULL,
		user_obs_tidy,
		NULL
	);

	return 0;
}
Example #5
0
static UINT8 UnArchiveValue(int TABLESINDEX)
{
	UINT8 type = READUINT8(save_p);
	switch (type)
	{
	case ARCH_NULL:
		lua_pushnil(gL);
		break;
	case ARCH_BOOLEAN:
		lua_pushboolean(gL, READUINT8(save_p));
		break;
	case ARCH_SIGNED:
		lua_pushinteger(gL, READFIXED(save_p));
		break;
	case ARCH_UNSIGNED:
		lua_pushinteger(gL, READANGLE(save_p));
		break;
	case ARCH_STRING:
	{
		char value[1024];
		READSTRING(save_p, value);
		lua_pushstring(gL, value);
		break;
	}
	case ARCH_TABLE:
	{
		UINT16 tid = READUINT16(save_p);
		lua_rawgeti(gL, TABLESINDEX, tid);
		if (lua_isnil(gL, -1))
		{
			lua_pop(gL, 1);
			lua_newtable(gL);
			lua_pushvalue(gL, -1);
			lua_rawseti(gL, TABLESINDEX, tid);
			return 2;
		}
		break;
	}
	case ARCH_MOBJINFO:
		LUA_PushUserdata(gL, &mobjinfo[READUINT16(save_p)], META_MOBJINFO);
		break;
	case ARCH_STATE:
		LUA_PushUserdata(gL, &states[READUINT16(save_p)], META_STATE);
		break;
	case ARCH_MOBJ:
		LUA_PushUserdata(gL, P_FindNewPosition(READUINT32(save_p)), META_MOBJ);
		break;
	case ARCH_PLAYER:
		LUA_PushUserdata(gL, &players[READUINT8(save_p)], META_PLAYER);
		break;
	case ARCH_MAPTHING:
		LUA_PushUserdata(gL, &mapthings[READUINT16(save_p)], META_MAPTHING);
		break;
	case ARCH_VERTEX:
		LUA_PushUserdata(gL, &vertexes[READUINT16(save_p)], META_VERTEX);
		break;
	case ARCH_LINE:
		LUA_PushUserdata(gL, &lines[READUINT16(save_p)], META_LINE);
		break;
	case ARCH_SIDE:
		LUA_PushUserdata(gL, &sides[READUINT16(save_p)], META_SIDE);
		break;
	case ARCH_SUBSECTOR:
		LUA_PushUserdata(gL, &subsectors[READUINT16(save_p)], META_SUBSECTOR);
		break;
	case ARCH_SECTOR:
		LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_SECTOR);
		break;
	case ARCH_MAPHEADER:
		LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_MAPHEADER);
		break;
	case ARCH_TEND:
		return 1;
	}
	return 0;
}
Example #6
0
/*cfg={}
cfg.ssid=""
cfg.pwd=""
cfg.ip (optional,default:11.11.11.1)
cfg.netmask(optional,default:255.255.255.0)
cfg.gateway(optional,default:11.11.11.1)
cfg.dnsSrv(optional,default:11.11.11.1)
cfg.retry_interval(optional,default:1000ms)
wifi.startap(cfg,function(optional))*/
static int lwifi_startap( lua_State* L )
{//4 stations Max
  network_InitTypeDef_st wNetConfig;
  size_t len=0;
  
  memset(&wNetConfig, 0x0, sizeof(network_InitTypeDef_st));
  
  if (!lua_istable(L, 1))
    return luaL_error( L, "table arg needed" );
//ssid  
  lua_getfield(L, 1, "ssid");
  if (!lua_isnil(L, -1)){  /* found? */
    if( lua_isstring(L, -1) )   // deal with the string
    {
      const char *ssid = luaL_checklstring( L, -1, &len );
      if(len>32)
        return luaL_error( L, "ssid:<32" );
      strncpy(wNetConfig.wifi_ssid,ssid,len);
    } 
    else
      return luaL_error( L, "wrong arg type:ssid" );
  }
  else
    return luaL_error( L, "arg: ssid needed" );
//pwd  
  lua_getfield(L, 1, "pwd");
  if (!lua_isnil(L, -1)){  /* found? */
    if( lua_isstring(L, -1) )   // deal with the string
    {
      const char *pwd = luaL_checklstring( L, -1, &len );
      if(len>64)
        return luaL_error( L, "pwd:<64" );
      if(len>0)
      strncpy(wNetConfig.wifi_key,pwd,len);
      else
      strcpy(wNetConfig.wifi_key,"");  
    } 
    else
      return luaL_error( L, "wrong arg type:pwd" );
  }
  else
    return luaL_error( L, "arg: pwd needed" );
  
//ip  
  lua_getfield(L, 1, "ip");
  if (!lua_isnil(L, -1)){  /* found? */
    if( lua_isstring(L, -1) )   // deal with the ssid string
    {
      const char *ip = luaL_checklstring( L, -1, &len );
      if(len>16)
        return luaL_error( L, "ip:<16" );
      if(is_valid_ip(ip)==false) 
        return luaL_error( L, "ip invalid" );
      strncpy(wNetConfig.local_ip_addr,ip,len);
    } 
    else
      return luaL_error( L, "wrong arg type:ip" );
  }
  else
  {
    strcpy(wNetConfig.local_ip_addr,"11.11.11.1");
    //return luaL_error( L, "arg: ip needed" );
  }
//netmask  
  lua_getfield(L, 1, "netmask");
  if (!lua_isnil(L, -1)){  /* found? */
    if( lua_isstring(L, -1) )   // deal with the ssid string
    {
      const char *netmask = luaL_checklstring( L, -1, &len );
      if(len>16)
        return luaL_error( L, "netmask:<16" );
      if(is_valid_ip(netmask)==false) 
        return luaL_error( L, "netmask invalid" );
      strncpy(wNetConfig.net_mask,netmask,len);
    } 
    else
      return luaL_error( L, "wrong arg type:netmask" );
  }
  else
  {
    strcpy(wNetConfig.net_mask,"255.255.255.0");
    //return luaL_error( L, "arg: netmask needed" );
  }
//gateway  
  lua_getfield(L, 1, "gateway");
  if (!lua_isnil(L, -1)){  /* found? */
    if( lua_isstring(L, -1) )   // deal with the ssid string
    {
      const char *gateway = luaL_checklstring( L, -1, &len );
      if(len>16)
        return luaL_error( L, "gateway:<16" );
      if(is_valid_ip(gateway)==false) 
        return luaL_error( L, "gateway invalid" );
      strncpy(wNetConfig.gateway_ip_addr,gateway,len);
    } 
    else
      return luaL_error( L, "wrong arg type:gateway" );
  }
  else
  {
    strcpy(wNetConfig.gateway_ip_addr,"11.11.11.1");
   // return luaL_error( L, "arg: gateway needed" );
  }
//dnsSrv  
  lua_getfield(L, 1, "dnsSrv");
  if (!lua_isnil(L, -1)){  /* found? */
    if( lua_isstring(L, -1) )   // deal with the ssid string
    {
      const char *dnsSrv = luaL_checklstring( L, -1, &len );
      if(len>16)
        return luaL_error( L, "dnsSrv:<16" );
      if(is_valid_ip(dnsSrv)==false) 
        return luaL_error( L, "dnsSrv invalid" );
      strncpy(wNetConfig.dnsServer_ip_addr,dnsSrv,len);
    } 
    else
      return luaL_error( L, "wrong arg type:dnsSrv" );
  }
  else
  {
    strcpy(wNetConfig.dnsServer_ip_addr,"11.11.11.1");
    //return luaL_error( L, "arg: dnsSrv needed" );
  }
//retry_interval
  signed retry_interval=0;
  lua_getfield(L, 1, "retry_interval");
  if (!lua_isnil(L, -1)){  /* found? */
      retry_interval= luaL_checknumber( L, -1 );
      if(retry_interval<=0)
        return luaL_error( L, "retry_interval:>0ms" );
  }
  else
     retry_interval = 1000; 
  wNetConfig.wifi_retry_interval = retry_interval;
  
  /*MCU_DBG("wifi_ssid:%s\r\n",wNetConfig.wifi_ssid);
  MCU_DBG("wifi_key:%s\r\n",wNetConfig.wifi_key);
  MCU_DBG("local_ip_addr:%s\r\n",wNetConfig.local_ip_addr);
  MCU_DBG("net_mask:%s\r\n",wNetConfig.net_mask);
  MCU_DBG("gateway_ip_addr:%s\r\n",wNetConfig.gateway_ip_addr);
  MCU_DBG("dnsServer_ip_addr:%s\r\n",wNetConfig.dnsServer_ip_addr);
  MCU_DBG("wifi_retry_interval:%d\r\n",wNetConfig.wifi_retry_interval);*/
  
//notify
  gL = L;
  if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION)
  {
    lua_pushvalue(L, 2);  // copy argument (func) to the top of stack
    if(wifi_status_changed_AP != LUA_NOREF)
      luaL_unref(L, LUA_REGISTRYINDEX, wifi_status_changed_AP);    
      
    wifi_status_changed_AP = luaL_ref(L, LUA_REGISTRYINDEX);
    MICOAddNotification( mico_notify_WIFI_STATUS_CHANGED, (void *)_micoNotify_WifiStatusHandler );
  } 
  else 
  {
    if(wifi_status_changed_AP != LUA_NOREF)
      luaL_unref(L, LUA_REGISTRYINDEX, wifi_status_changed_AP);
    wifi_status_changed_AP = LUA_NOREF;
  }
//start  
  wNetConfig.dhcpMode = DHCP_Server;  
  wNetConfig.wifi_mode = Soft_AP;
  micoWlanStart(&wNetConfig);  
  return 0;  
}
Example #7
0
int os_locate(lua_State* L)
{
	int i, nArgs, vars;
	const char* premake_path = getenv("PREMAKE_PATH");

	nArgs = lua_gettop(L);

	/* see if the global environment variables have been set yet */
	lua_getglobal(L, "_USER_HOME_DIR");
	vars = !lua_isnil(L, -1);
	lua_pop(L, 1);

	for (i = 1; i <= nArgs; ++i) {
		/* Direct path to file? Return fully qualified version */
		if (do_isfile(lua_tostring(L, i))) {
			lua_pushcfunction(L, path_getabsolute);
			lua_pushvalue(L, i);
			lua_call(L, 1, 1);
			return 1;
		}

		/* Search for it... */
		lua_pushcfunction(L, os_pathsearch);
		lua_pushvalue(L, i);

		/* ...relative to the main project script */
		if (vars) {
			lua_getglobal(L, "_MAIN_SCRIPT_DIR");
		}

		/* ...relative to the CWD */
		lua_pushstring(L, ".");

		/* ...on the paths specified by --scripts, if set */
		if (scripts_path) {
			lua_pushstring(L, scripts_path);
		}

		/* ... relative to ~/.premake */
		if (vars) {
			lua_getglobal(L, "_USER_HOME_DIR");
			lua_pushstring(L, "/.premake");
			lua_concat(L, 2);
		}

		/* ...on the PREMAKE_PATH environment variable, if set */
		if (premake_path) {
			lua_pushstring(L, premake_path);
		}

		/* ...relative to the Premake executable */
		if (vars) {
			lua_getglobal(L, "_PREMAKE_DIR");
		}

		/* ...in ~/Library/Application Support/Premake (for OS X) */
		if (vars) {
			lua_getglobal(L, "_USER_HOME_DIR");
			lua_pushstring(L, "/Library/Application Support/Premake");
			lua_concat(L, 2);
		}

		/* ...in the expected Unix-y places */
		lua_pushstring(L, "/usr/local/share/premake");
		lua_pushstring(L, "/usr/share/premake");

		lua_call(L, lua_gettop(L) - nArgs - 1, 1);
		if (!lua_isnil(L, -1)) {
			lua_pushcfunction(L, path_join);
			lua_pushvalue(L, -2);
			lua_pushvalue(L, i);
			lua_call(L, 2, 1);
			return 1;
		}

		lua_pop(L, 1);
	}

	return 0;
}
Example #8
0
// Called from C to open a pload
static int addon_output_pload_open(void *obj, void **priv, struct pload *pload) {

	struct addon_instance_priv *p = obj;

	// Lock the output
	pom_mutex_lock(&p->lock);

	lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self

	struct addon_output_pload_priv *ppriv = malloc(sizeof(struct addon_output_pload_priv));
	if (!ppriv) {
		pom_mutex_unlock(&p->lock);
		pom_oom(sizeof(struct addon_output_pload_priv));
		return POM_ERR;
	}
	memset(ppriv, 0, sizeof(struct addon_output_pload_priv));

	*priv = ppriv;

	// Get the __pload_listener table
	lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener

	// Get the open function
	lua_getfield(p->L, -1, "open"); // Stack : self, __pload_listener, open_func

	// Check if there is an open function
	if (lua_isnil(p->L, -1)) {
		pom_mutex_unlock(&p->lock);
		lua_pop(p->L, 3); // Stack : empty
		return POM_OK;
	}

	// Add self
	lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, open_func, self

	// Create a new table for the pload priv and store it into __pload_listener
	lua_newtable(p->L); // Stack : self, __pload_listener, open_func, self, pload_priv_table

	// Add output_pload_data to it
	addon_pload_data_push(p->L); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_data
	lua_setfield(p->L, -2, "__pload_data"); // Stack : self, __pload_listener, open_func, self, pload_priv_table

	// Add the new priv to the __pload_listener table
	lua_pushlightuserdata(p->L, ppriv); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_priv
	lua_pushvalue(p->L, -2); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_priv, pload_priv_table
	lua_settable(p->L, -6); // Stack : self, __pload_listener, open_func, self, pload_priv_table

	// Add the pload to the args
	addon_pload_push(p->L, pload, ppriv); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload


	// Call the open function
	addon_pcall(p->L, 3, 1); // Stack : self, __pload_listener, result

	int res = 0;
	if (!lua_isboolean(p->L, -1)) {
		pomlog(POMLOG_WARN "LUA coding error: pload open function result must be a boolean");
	} else {
		res = lua_toboolean(p->L, -1);
	}

	if (!res) { // The payload doesn't need to be processed, remove the payload_priv_table and the __pload_data
		lua_pushlightuserdata(p->L, ppriv); // Stack : self, __pload_listener, result, pload_priv
		lua_pushnil(p->L); // Stack : self, __pload_listener, result, pload_priv, nil
		lua_settable(p->L, -4); // Stack : self, __pload_listener, result
		lua_pushnil(p->L); // Stack : self, __pload_listener, result, nil
		lua_setfield(p->L, -3, "__pload_data"); // Stack : self, __pload_listener, result
	}

	// Remove leftovers
	lua_pop(p->L, 3); // Stack : empty
	pom_mutex_unlock(&p->lock);

	return POM_OK;
}
Example #9
0
// Called from C to write a pload
static int addon_output_pload_write(void *output_priv, void *pload_instance_priv, void *data, size_t len) {

	struct addon_output_pload_priv *ppriv = pload_instance_priv;
	struct addon_instance_priv *p = output_priv;

	pom_mutex_lock(&p->lock);

	// First process all the plugins attached to this pload
	struct addon_output_pload_plugin *tmp;
	for (tmp = ppriv->plugins; tmp; tmp = tmp->next) {
		if (tmp->is_err)
			continue;

		if (addon_plugin_pload_write(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv, data, len) != POM_OK) {
			addon_plugin_pload_close(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv);
			tmp->is_err = 1;
		}
	}

	lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self

	lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener

	// Get the write function
	lua_getfield(p->L, -1, "write"); // Stack : self, __pload_listener, write_func
	
	// Check if there is a write function
	if (lua_isnil(p->L, -1)) {
		lua_pop(p->L, 3); // Stack : empty
		pom_mutex_unlock(&p->lock);
		return POM_OK;
	}

	// Setup args
	lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, write_func, self
	lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, write_func, self, pload_priv
	lua_gettable(p->L, -4); // Stack : self, __pload_listener, write_func, self, pload_priv_table

	if (lua_isnil(p->L, -1)) {
		// There is no pload_priv_table, payload doesn't need to be processed
		lua_pop(p->L, 5); // Stack : empty
		pom_mutex_unlock(&p->lock);
		return POM_OK;
	}

	lua_getfield(p->L, -1, "__pload_data"); // Stack : self, __pload_listener, write_func, self, pload_priv_table, pload_data

	// Update the pload_data
	addon_pload_data_update(p->L, -1, data, len);
	pom_mutex_unlock(&p->lock);

	int res = addon_pcall(p->L, 3, 1); // Stack : self, __pload_listener, result

	int write_res = 0;

	if (res == POM_OK) {
		if (!lua_isboolean(p->L, -1)) {
			pomlog(POMLOG_WARN "LUA coding error: pload write function result must be a boolean");
		} else {
			write_res = lua_toboolean(p->L, -1);
		}
	}

	if (!write_res) {
		// Remove the pload_priv_table since it failed
		lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, result, pload_priv
		lua_pushnil(p->L); // Stack : self, __pload_listener, result, pload_priv, nil
		lua_settable(p->L, -4); // Stack : self, __pload_listener, result
	}

	lua_pop(p->L, 3); // Stack : empty

	pom_mutex_unlock(&p->lock);

	return POM_OK;
}
Example #10
0
/* args-opts -- proc/nil error */
static int ex_spawn(lua_State *L)
{
  struct spawn_params *params;
  int have_options;
  switch (lua_type(L, 1)) {
  default: return luaL_typerror(L, 1, "string or table");
  case LUA_TSTRING:
    switch (lua_type(L, 2)) {
    default: return luaL_typerror(L, 2, "table");
    case LUA_TNONE: have_options = 0; break;
    case LUA_TTABLE: have_options = 1; break;
    }
    break;
  case LUA_TTABLE:
    have_options = 1;
	/* avoid issues with strict.lua */
	lua_pushstring(L, "command");		/* opts ... cmd */
	lua_rawget(L, 1);
    if (!lua_isnil(L, -1)) {
      /* convert {command=command,arg1,...} to command {arg1,...} */
      lua_insert(L, 1);                 /* cmd opts ... */
    }
    else {
      /* convert {arg0,arg1,...} to arg0 {arg1,...} */
      size_t i, n = lua_objlen(L, 1);
      lua_rawgeti(L, 1, 1);             /* opts ... nil cmd */
      lua_insert(L, 1);                 /* cmd opts ... nil */
      for (i = 2; i <= n; i++) {
        lua_rawgeti(L, 2, i);           /* cmd opts ... nil argi */
        lua_rawseti(L, 2, i - 1);       /* cmd opts ... nil */
      }
      lua_rawseti(L, 2, n);             /* cmd opts ... */
    }
    if (lua_type(L, 1) != LUA_TSTRING)
      return luaL_error(L, "bad command option (string expected, got %s)",
                        luaL_typename(L, 1));
    break;
  }
  params = spawn_param_init(L);
  /* get filename to execute */
  spawn_param_filename(params);
  /* get arguments, environment, and redirections */
  if (have_options) {
    lua_getfield(L, 2, "args");         /* cmd opts ... argtab */
    switch (lua_type(L, -1)) {
    default:
      return luaL_error(L, "bad args option (table expected, got %s)",
                        luaL_typename(L, -1));
    case LUA_TNIL:
      lua_pop(L, 1);                    /* cmd opts ... */
      lua_pushvalue(L, 2);              /* cmd opts ... opts */
      if (0) /*FALLTHRU*/
    case LUA_TTABLE:
      if (lua_objlen(L, 2) > 0)
        return
          luaL_error(L, "cannot specify both the args option and array values");
      spawn_param_args(params);         /* cmd opts ... */
      break;
    }
    lua_getfield(L, 2, "env");          /* cmd opts ... envtab */
    switch (lua_type(L, -1)) {
    default:
      return luaL_error(L, "bad env option (table expected, got %s)",
                        luaL_typename(L, -1));
    case LUA_TNIL:
      break;
    case LUA_TTABLE:
      spawn_param_env(params);          /* cmd opts ... */
      break;
    }

    lua_getfield(L, 2, "show");          /* cmd opts ... envtab */
    spawn_param_show(params, lua_type(L, -1) == LUA_TBOOLEAN ? lua_toboolean(L, -1) : 0);

    lua_getfield(L, 2, "shell");          /* cmd opts ... envtab */
    spawn_param_useshell(params, lua_type(L, -1) == LUA_TBOOLEAN ? lua_toboolean(L, -1) : 1);

    lua_getfield(L, 2, "detach");          /* cmd opts ... envtab */
    spawn_param_detach(params, lua_type(L, -1) == LUA_TBOOLEAN ? lua_toboolean(L, -1) : 0);

    get_redirect(L, 2, "stdin", params);    /* cmd opts ... */
    get_redirect(L, 2, "stdout", params);   /* cmd opts ... */
    get_redirect(L, 2, "stderr", params);   /* cmd opts ... */
  }
  return spawn_param_execute(params);   /* proc/nil error */
}
Example #11
0
LUAMODULE_API int luaopen_ex_core(lua_State *L)
{
  const char *name = lua_tostring(L, 1);
  int ex;
  const luaL_reg ex_iolib[] = {
    {"pipe",       ex_pipe},
#define ex_iofile_methods (ex_iolib + 1)
    {"lock",       ex_lock},
    {"unlock",     ex_lock},
    {0,0} };
  const luaL_reg ex_oslib[] = {
    /* environment */
    {"getenv",     ex_getenv},
    {"setenv",     ex_setenv},
    {"environ",    ex_environ},
    /* file system */
    {"access",     ex_access},
    {"getcwd",     ex_getcwd},
    {"chdir",      ex_chdir},
    {"chmod",      ex_chmod},
    {"mkdir",      ex_mkdir},
    {"remove",     ex_remove},
    {"dir",        ex_dir},
    {"dirent",     ex_dirent},
    {"copyfile",   ex_copyfile},
    {"movefile",   ex_movefile},
    {"touch",   ex_touch},
    {"stdin_binary", ex_stdin_binary},
    {"stdout_binary", ex_stdout_binary},
    /* process control */
    {"sleep",      ex_sleep},
    {"spawn",      ex_spawn},
    {0,0} };
  const luaL_reg ex_diriter_methods[] = {
    {"__gc",       diriter_close},
    {0,0} };
  const luaL_reg ex_process_methods[] = {
    {"__tostring", process_tostring},
#define ex_process_functions (ex_process_methods + 1)
    {"wait",       process_wait},
    {"__gc",       process_close},
    {0,0} };
  /* diriter metatable */
  luaL_newmetatable(L, DIR_HANDLE);           /* . D */
  luaL_register(L, 0, ex_diriter_methods);    /* . D */
  /* proc metatable */
  luaL_newmetatable(L, PROCESS_HANDLE);       /* . P */
  luaL_register(L, 0, ex_process_methods);    /* . P */
  lua_pushvalue(L, -1);                       /* . P P */
  lua_setfield(L, -2, "__index");             /* . P */
  /* make all functions available via ex. namespace */
  luaL_register(L, name, ex_oslib);           /* . P ex */
  luaL_register(L, 0, ex_iolib);
  copyfields(L, ex_process_functions, -2, -1);
  ex = lua_gettop(L);
  /* extend the os table */
  lua_getglobal(L, "os");                     /* . os */
  if (lua_isnil(L, -1)) return luaL_error(L, "os not loaded");
  copyfields(L, ex_oslib, ex, -1);
  luaopen_os_path(L);
  /* extend the io table */
  lua_getglobal(L, "io");                     /* . io */
  if (lua_isnil(L, -1)) return luaL_error(L, "io not loaded");
  copyfields(L, ex_iolib, ex, -1);
//  copyfields(L, ex_iolib, ex, -1);
  lua_getfield(L, ex, "pipe");                /* . io ex_pipe */
  newfenv(L, pipe_close);  /* create environment for 'popen' */
  lua_setfenv(L, -2);  /* set fenv for 'popen' */
  lua_pop(L, 1);  /* pop 'popen' */
  /* extend the io.file metatable */
  luaL_getmetatable(L, LUA_FILEHANDLE);       /* . F */
  if (lua_isnil(L, -1)) return luaL_error(L, "can't find FILE* metatable");
  copyfields(L, ex_iofile_methods, ex, -1);
  luaopen_windows_hkey(L);
  return 1;
}
static int gritobj_newindex (lua_State *L)
{
TRY_START
        check_args(L,3);
        GET_UD_MACRO(GritObjectPtr,self,1,GRITOBJ_TAG);
        std::string key = check_string(L,2);

        if (key=="destroy") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="near") {
                if (lua_isnil(L,3)) {
                        self->setNearObj(self,GritObjectPtr());
                } else {
                        GET_UD_MACRO(GritObjectPtr,v,3,GRITOBJ_TAG);
                        self->setNearObj(self,v);
                }
        } else if (key=="far") {
                if (lua_isnil(L,3)) {
                        self->setNearObj(self,GritObjectPtr());
                } else {
                        GET_UD_MACRO(GritObjectPtr,v,3,GRITOBJ_TAG);
                        self->setFarObj(self,v);
                }
        } else if (key=="fade") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="updateSphere") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="pos") {
                self->updateSphere(check_v3(L,3));
        } else if (key=="renderingDistance") {
                self->updateSphere(check_float(L,3));
        } else if (key=="getSphere") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="activated") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="deactivate") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="activate") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="instance") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="hintAdvancePrepare") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="getAdvancePrepareHints") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="destroyed") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="class") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="className") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="name") {
                my_lua_error(L,"Not a writeable GritObject member: "+key);
        } else if (key=="needsFrameCallbacks") {
                self->setNeedsFrameCallbacks(self, check_bool(L,3));
        } else if (key=="needsStepCallbacks") {
                self->setNeedsStepCallbacks(self, check_bool(L,3));
        } else {
                GritClass *c = self->getClass();
                if (c==NULL) my_lua_error(L,"GritObject destroyed");
                const char *err = self->userValues.luaSet(L);
                if (err) my_lua_error(L, err);
        }

        return 0;
TRY_END
}
static int gritobj_index (lua_State *L)
{
TRY_START
        check_args(L,2);
        GET_UD_MACRO(GritObjectPtr,self,1,GRITOBJ_TAG);
        std::string key = check_string(L,2);
        if (key=="destroy") {
                push_cfunction(L,gritobj_destroy);
        } else if (key=="activated") {
                lua_pushboolean(L,self->isActivated());
        } else if (key=="near") {
                push_gritobj(L,self->getNearObj());
        } else if (key=="far") {
                push_gritobj(L,self->getFarObj());
        } else if (key=="fade") {
                lua_pushnumber(L,self->getFade());
        } else if (key=="updateSphere") {
                push_cfunction(L,gritobj_update_sphere);
        } else if (key=="pos") {
                push_v3(L, self->getPos());
        } else if (key=="renderingDistance") {
                lua_pushnumber(L, self->getR());
        } else if (key=="deactivate") {
                push_cfunction(L,gritobj_deactivate);
        } else if (key=="activate") {
                push_cfunction(L,gritobj_activate);
        } else if (key=="instance") {
                self->pushLuaTable(L);
        } else if (key=="addDiskResource") {
                push_cfunction(L,gritobj_add_disk_resource);
        } else if (key=="reloadDiskResources") {
                push_cfunction(L,gritobj_reload_disk_resource);
/*
        } else if (key=="getAdvancePrepareHints") {
                push_cfunction(L,gritobj_get_advance_prepare_hints);
*/
        } else if (key=="destroyed") {
                lua_pushboolean(L,self->getClass()==NULL);
        } else if (key=="class") {
                GritClass *c = self->getClass();
                if (c==NULL) my_lua_error(L,"GritObject destroyed");
                push_gritcls(L,c);
        } else if (key=="className") {
                GritClass *c = self->getClass();
                if (c==NULL) my_lua_error(L,"GritObject destroyed");
                lua_pushstring(L,c->name.c_str());
        } else if (key=="name") {
                lua_pushstring(L,self->name.c_str());
        } else if (key=="needsFrameCallbacks") {
                lua_pushboolean(L,self->getNeedsFrameCallbacks());
        } else if (key=="needsStepCallbacks") {
                lua_pushboolean(L,self->getNeedsStepCallbacks());
        } else if (key=="dump") {
                self->userValues.dump(L);
        } else {
                GritClass *c = self->getClass();
                if (c==NULL) my_lua_error(L,"GritObject destroyed");
                const char *err = self->userValues.luaGet(L);
                if (err) my_lua_error(L, err);
                if (!lua_isnil(L,-1)) return 1;
                lua_pop(L,1);
                // try class instead
                c->get(L,key);
        }
        return 1;
TRY_END
}
Example #14
0
			typedef typename boost::mpl::if_<boost::is_void<R>
				, luabind::detail::proxy_member_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
				, luabind::detail::proxy_member_caller<R, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type proxy_type;

			// this will be cleaned up by the proxy object
			// once the call has been made

			// TODO: what happens if this virtual function is
			// dispatched from a lua thread where the state
			// pointer is different?

			// get the function
			lua_State* L = m_self.state();
			m_self.get(L);
			assert(!lua_isnil(L, -1));
			detail::do_call_member_selection(L, name);

			if (lua_isnil(L, -1))
			{
				lua_pop(L, 1);
				throw std::runtime_error("Attempt to call nonexistent function");
			}

			// push the self reference as the first parameter
			m_self.get(L);

			// now the function and self objects
			// are on the stack. These will both
			// be popped by pcall
			return proxy_type(L, args);
Example #15
0
	jass::jreal_t    read_real(lua_State* L, int index)
	{
		if (lua_isnil(L, index)) return 0;
		return jass::to_real(jreal::read<float>(L, index));
	}
Example #16
0
// Called from C to close a pload
static int addon_output_pload_close(void *output_priv, void *pload_instance_priv) {

	struct addon_output_pload_priv *ppriv = pload_instance_priv;
	struct addon_instance_priv *p = output_priv;
	int res = POM_OK;


	pom_mutex_lock(&p->lock);

	// Process all the plugins attached to this pload
	struct addon_output_pload_plugin *tmp;
	for (tmp = ppriv->plugins; tmp; tmp = tmp->next) {
		if (tmp->is_err)
			continue;
		addon_plugin_pload_close(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv);
	}

	lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self
	lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener

	// Get the pload_priv_table
	lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, pload_priv
	lua_gettable(p->L, -2); // Stack : self, __pload_listener, pload_priv_table

	if (lua_isnil(p->L, -1)) {
		// There is no pload_priv_table, the payload doesn't need to be processed
		lua_pop(p->L, 3);
		goto cleanup;
	}

	// Remove the payload_priv_table from __pload_listener
	lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, pload_priv_table, pload_priv
	lua_pushnil(p->L); // Stack : self, __pload_listener, pload_priv_table, pload_priv, nil
	lua_settable(p->L, -4); // Stack : self, __pload_listener, pload_priv_table

	// Get the close function
	lua_getfield(p->L, -2,  "close"); // Stack : self, __pload_listener, pload_priv_table, close_func

	if (lua_isnil(p->L, -1)) {
		// There is no close function
		lua_pop(p->L, 4); // Stack : empty
		goto cleanup;
	}


	// Setup args
	lua_pushvalue(p->L, 1); // Stack : self, __pload_listener, pload_priv_table, close_func, self
	lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, pload_priv_table, close_func, self, pload_priv_table

	res = addon_pcall(p->L, 2, 0); // Stack : self, __pload_listener, pload_priv_table

	lua_pop(p->L, 3); // Stack : empty

cleanup:

	pom_mutex_unlock(&p->lock);

	while (ppriv->plugins) {
		tmp = ppriv->plugins;
		ppriv->plugins = tmp->next;
		free(tmp);
	}

	free(ppriv);


	return res;
}
Example #17
0
/*
** Read the options specified in the ini file.
**
*/
void CMeasureScript::ReadOptions(CConfigParser& parser, const WCHAR* section)
{
	CMeasure::ReadOptions(parser, section);

	std::wstring file = parser.ReadString(section, L"ScriptFile", L"");

	if (!file.empty())
	{
		if (m_MeterWindow)
		{
			m_MeterWindow->MakePathAbsolute(file);
		}

		if (!m_Initialized ||
			wcscmp(file.c_str(), m_ScriptFile.c_str()) != 0)
		{
			DeleteLuaScript();

			lua_State* L = LuaManager::GetState();
			m_ScriptFile = file;
			m_LuaScript = new LuaScript(m_ScriptFile.c_str());

			if (m_LuaScript->IsInitialized())
			{
				m_HasInitializeFunction = m_LuaScript->IsFunction(g_InitializeFunctionName);
				m_HasUpdateFunction = m_LuaScript->IsFunction(g_UpdateFunctionName);
				m_HasGetStringFunction = m_LuaScript->IsFunction(g_GetStringFunctionName);  // For backwards compatbility

				if (m_HasGetStringFunction)
				{
					LogWithArgs(LOG_WARNING, L"Script: Using deprecated GetStringValue() in [%s]", m_Name.c_str());
				}

				lua_rawgeti(L, LUA_GLOBALSINDEX, m_LuaScript->GetRef());

				*(CMeterWindow**)lua_newuserdata(L, sizeof(CMeterWindow*)) = m_MeterWindow;
				lua_getglobal(L, "CMeterWindow");
				lua_setmetatable(L, -2);
				lua_setfield(L, -2, "SKIN");

				*(CMeasure**)lua_newuserdata(L, sizeof(CMeasure*)) = this;
				lua_getglobal(L, "CMeasure");
				lua_setmetatable(L, -2);
				lua_setfield(L, -2, "SELF");

				// For backwards compatibility
				lua_getfield(L, -1, "PROPERTIES");
				if (lua_isnil(L, -1) == 0)
				{
					lua_pushnil(L);
					
					// Look in the table for values to read from the section
					while (lua_next(L, -2))
					{
						lua_pop(L, 1);
						const char* strKey = lua_tostring(L, -1);

						std::wstring wstrKey = ConvertToWide(strKey);
						const std::wstring& wstrValue = parser.ReadString(section, wstrKey.c_str(), L"");

						if (!wstrValue.empty())
						{
							LuaManager::PushWide(L, wstrValue.c_str());
							lua_setfield(L, -3, strKey);
						}
					}
				}

				// Pop PROPERTIES table and our table
				lua_pop(L, 2);
			}
			else
			{
				DeleteLuaScript();
			}
		}
	}
	else
	{
		LogWithArgs(LOG_ERROR, L"Script: File not valid in [%s]", m_Name.c_str());
		DeleteLuaScript();
	}
}
Example #18
0
// Called from lua to start listening to files
static int addon_output_pload_listen_start(lua_State *L) {

	// Args should be :
	// 1) self
	// 2) open function
	// 3) write function
	// 4) close function
	// 5) filter if any

	// Push nill if additional functions are missing
	while (lua_gettop(L) < 5)
		lua_pushnil(L);

	// Stack : instance, read_func, write_func, close_func

	// Get the output
	struct addon_instance_priv *p = addon_output_get_priv(L, 1);

	if (!lua_isfunction(L, 2) && !lua_isfunction(L, 3) && !lua_isfunction(L, 4))
		luaL_error(L, "At least one function should be provided to pload_listen_start()");

	// Check if we are already listening or not
	lua_getfield(L, 1, "__pload_listener");
	if (!lua_isnil(L, -1))
		luaL_error(L, "The output is already listening for payloads");

	struct filter *filter = NULL;

	if (!lua_isnoneornil(L, 5)) {
		const char *filter_str = luaL_checkstring(L, 5);
		filter = pload_filter_compile((char*)filter_str);
		if (!filter)
			luaL_error(L, "Error while parsing filter \"%s\"", filter_str);
	}

	if (pload_listen_start(p, NULL, filter, addon_output_pload_open, addon_output_pload_write, addon_output_pload_close) != POM_OK)
		luaL_error(L, "Error while registering the payload listener");


	// Create table to track pload listener functions
	lua_pushliteral(L, "__pload_listener");
	lua_newtable(L);

	if (!lua_isnil(L, 2)) {
		lua_pushliteral(L, "open");
		lua_pushvalue(L, 2);
		lua_settable(L, -3);
	}

	if (!lua_isnil(L, 3)) {
		lua_pushliteral(L, "write");
		lua_pushvalue(L, 3);
		lua_settable(L, -3);
	}

	if (!lua_isnil(L, 4)) {
		lua_pushliteral(L, "close");
		lua_pushvalue(L, 4);
		lua_settable(L, -3);
	}

	lua_settable(L, 1);
	
	return 0;
}
Example #19
0
bool LuaInterface::isNil(int index)
{
    assert(hasIndex(index));
    return lua_isnil(L, index);
}
Example #20
0
void evalGenericCommand(redisClient *c, int evalsha)
{
    lua_State *lua = server.lua;
    char funcname[43];
    long long numkeys;
    int delhook = 0;

    /* We want the same PRNG sequence at every call so that our PRNG is
     * not affected by external state.
     *
     * 在每次执行 EVAL 时重置随机 seed ,从而保证可以生成相同的随机序列。
     */
    redisSrand48(0);

    /* We set this flag to zero to remember that so far no random command
     * was called. This way we can allow the user to call commands like
     * SRANDMEMBER or RANDOMKEY from Lua scripts as far as no write command
     * is called (otherwise the replication and AOF would end with non
     * deterministic sequences).
     *
     * Thanks to this flag we'll raise an error every time a write command
     * is called after a random command was used.
     *
     * 用两个变量,对命令进行检查
     * 确保在调用随机命令之后,再调用写命令将出现错误
     */
    server.lua_random_dirty = 0;
    server.lua_write_dirty = 0;

    /* Get the number of arguments that are keys */
    // 获取输入键的数量
    if (getLongLongFromObjectOrReply(c,c->argv[2],&numkeys,NULL) != REDIS_OK)
        return;
    // 对键的正确性做一个快速检查
    if (numkeys > (c->argc - 3))
    {
        addReplyError(c,"Number of keys can't be greater than number of args");
        return;
    }

    /* We obtain the script SHA1, then check if this function is already
     * defined into the Lua state */
    // 组合出函数的名字,例如 f_282297a0228f48cd3fc6a55de6316f31422f5d17
    funcname[0] = 'f';
    funcname[1] = '_';
    if (!evalsha)
    {
        /* Hash the code if this is an EVAL call */
        // 如果执行的是 EVAL 命令,那么计算脚本的 SHA1 校验和
        sha1hex(funcname+2,c->argv[1]->ptr,sdslen(c->argv[1]->ptr));
    }
    else
    {
        // 如果执行的是 EVALSHA 命令,直接使用传入的 SHA1 值
        /* We already have the SHA if it is a EVALSHA */
        int j;
        char *sha = c->argv[1]->ptr;

        for (j = 0; j < 40; j++)
            funcname[j+2] = tolower(sha[j]);
        funcname[42] = '\0';
    }

    /* Try to lookup the Lua function */
    // 按名查找函数
    lua_getglobal(lua, funcname);
    if (lua_isnil(lua,1))
    {

        // 没找到脚本相应的脚本

        lua_pop(lua,1); /* remove the nil from the stack */
        /* Function not defined... let's define it if we have the
         * body of the funciton. If this is an EVALSHA call we can just
         * return an error. */
        if (evalsha)
        {
            // 如果执行的是 EVALSHA ,返回脚本未找到错误
            addReply(c, shared.noscripterr);
            return;
        }
        // 如果执行的是 EVAL ,那么创建并执行新函数,然后将代码添加到脚本字典中
        if (luaCreateFunction(c,lua,funcname,c->argv[1]) == REDIS_ERR) return;
        /* Now the following is guaranteed to return non nil */
        lua_getglobal(lua, funcname);
        redisAssert(!lua_isnil(lua,1));
    }

    /* Populate the argv and keys table accordingly to the arguments that
     * EVAL received. */
    // 设置 KEYS 和 ARGV 全局变量到 Lua 环境
    luaSetGlobalArray(lua,"KEYS",c->argv+3,numkeys);
    luaSetGlobalArray(lua,"ARGV",c->argv+3+numkeys,c->argc-3-numkeys);

    /* Select the right DB in the context of the Lua client */
    // 为 Lua 所属的(伪)客户端设置数据库
    selectDb(server.lua_client,c->db->id);

    /* Set an hook in order to be able to stop the script execution if it
     * is running for too much time.
     *
     * 设置一个钩子,用于在运行时间过长时停止脚本的运作。
     *
     * We set the hook only if the time limit is enabled as the hook will
     * make the Lua script execution slower.
     *
     * 只在开启了时间限制选项时使用钩子,因为它会拖慢脚本的运行速度。
     */
    // 调用客户端
    server.lua_caller = c;
    // 脚本开始时间
    server.lua_time_start = ustime()/1000;
    // 是否杀死脚本
    server.lua_kill = 0;
    // 只在开启时间限制时使用钩子
    if (server.lua_time_limit > 0 && server.masterhost == NULL)
    {
        lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000);
        delhook = 1;
    }

    /* At this point whatever this script was never seen before or if it was
     * already defined, we can call it. We have zero arguments and expect
     * a single return value. */
    // 执行脚本(所属的函数)
    if (lua_pcall(lua,0,1,0))
    {

        // 以下是脚本执行出错的代码。。。

        // 删除钩子
        if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */

        // 脚本执行已超时
        if (server.lua_timedout)
        {
            // 清除超时 FLAG
            server.lua_timedout = 0;
            /* Restore the readable handler that was unregistered when the
             * script timeout was detected. */
            // 将超时钩子里删除的读事件重新加上
            aeCreateFileEvent(server.el,c->fd,AE_READABLE,
                              readQueryFromClient,c);
        }

        // 清空调用者
        server.lua_caller = NULL;
        // 更新目标数据库
        selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */
        addReplyErrorFormat(c,"Error running script (call to %s): %s\n",
                            funcname, lua_tostring(lua,-1));
        // 弹出函数
        lua_pop(lua,1);
        // 执行完整的废料回首循环(full garbage-collection cycle)
        lua_gc(lua,LUA_GCCOLLECT,0);
        // 返回
        return;
    }

    // 以下是脚本执行成功时执行的代码。。。

    // 删除钩子
    if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */

    // 清空超时 FLAG
    server.lua_timedout = 0;

    // 清空调用者
    server.lua_caller = NULL;

    // 更新 DB
    selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */

    // 将 Lua 回复转换成 Redis 回复
    luaReplyToRedisReply(c,lua);

    // 执行 1 步渐进式 GC
    lua_gc(lua,LUA_GCSTEP,1);

    /* If we have slaves attached we want to replicate this command as
     * EVAL instead of EVALSHA. We do this also in the AOF as currently there
     * is no easy way to propagate a command in a different way in the AOF
     * and in the replication link.
     *
     * 如果有附属节点,那么使用 EVAL 而不是 EVALSHA 来传播脚本
     * 因为目前还没有代码可以检测脚本是否已经传送到附属节点中
     *
     * IMPROVEMENT POSSIBLE:
     * 1) Replicate this command as EVALSHA in the AOF.
     * 2) Remember what slave already received a given script, and replicate
     *    the EVALSHA against this slaves when possible.
     */
    // 如果执行的是 EVALSHA 命令
    if (evalsha)
    {
        // 取出脚本代码体(body)
        robj *script = dictFetchValue(server.lua_scripts,c->argv[1]->ptr);

        redisAssertWithInfo(c,NULL,script != NULL);
        // 重写客户端命令为 EVAL
        rewriteClientCommandArgument(c,0,
                                     resetRefCount(createStringObject("EVAL",4)));
        rewriteClientCommandArgument(c,1,script);
    }
}
Example #21
0
/*
| Executes a subprocess. Does not wait for it to return.
|
| Params on Lua stack:
|
|    1: Path to binary to call
|    2: List of string as arguments
|         or "<" in which case the next argument is a string
|         that will be piped on stdin.
|         The arguments will follow that one.
|
| Returns (Lua stack) the pid on success, 0 on failure.
*/
static int
l_exec( lua_State *L )
{
	// the binary to call
	const char *binary = luaL_checkstring(L, 1);

	// number of arguments
	int argc = lua_gettop( L ) - 1;

	// the pid spawned
	pid_t pid;

	// the arguments position in the lua arguments
	int li = 1;

	// the pipe to text
	char const * pipe_text = NULL;

	// the pipes length
	size_t pipe_len = 0;

	// the arguments
	char const ** argv;

	// pipe file descriptors
	int pipefd[ 2 ];

	int i;

	// expands tables
	// and removes nils
	for( i = 1; i <= lua_gettop( L ); i++ )
	{
		if( lua_isnil( L, i ) )
		{
			lua_remove( L, i );
			i--;
			argc--;
			continue;
		}

		if( lua_istable( L, i ) )
		{
			int tlen;
			int it;
			lua_checkstack( L, lua_gettop( L ) + lua_objlen( L, i ) + 1 );

			// moves table to top of stack
			lua_pushvalue( L, i );
			lua_remove( L, i );
			argc--;
			tlen = lua_objlen( L, -1 );

			for( it = 1; it <= tlen; it++ )
			{
				lua_pushinteger( L, it );
				lua_gettable( L, -2 );
				lua_insert( L, i );
				i++;
				argc++;
			}
			i--;
			lua_pop( L, 1 );
		}
	}

	// writes a log message (if needed).
	if( check_logcat( "Exec" ) <= settings.log_level )
	{
		lua_checkstack( L, lua_gettop( L ) + argc * 3 + 2 );
		lua_pushvalue( L, 1 );

		for( i = 1; i <= argc; i++ )
		{
			lua_pushstring( L, " [" );
			lua_pushvalue( L, i + 1 );
			lua_pushstring( L, "]" );
		}

		lua_concat( L, 3 * argc + 1 );

		// replaces midfile 0 chars by linefeed
		size_t len = 0;
		const char * cs = lua_tolstring( L, -1, &len );
		char * s = s_calloc( len + 1, sizeof( char ) ); 

		for( i = 0; i < len; i++ )
		{
			s[ i ] = cs[ i ] ? cs[ i ] : '\n';
		}

		logstring0(
			LOG_DEBUG, "Exec",
			s
		);

		free( s );

		lua_pop( L, 1 );
	}

	if( argc >= 2 && !strcmp( luaL_checkstring( L, 2 ), "<" ) )
	{
		// pipes something into stdin
		if( !lua_isstring( L, 3 ) )
		{
			logstring(
				"Error",
				"in spawn(), expected a string after pipe '<'"
			);

			exit( -1 );
		}

		pipe_text = lua_tolstring( L, 3, &pipe_len );

		if( strlen( pipe_text ) > 0 )
		{
			// creates the pipe
			if( pipe( pipefd ) == -1 )
			{
				logstring( "Error", "cannot create a pipe!" );

				exit( -1 );
			}

			// always closes the write end for child processes
			close_exec_fd( pipefd[ 1 ] );

			// sets the write end on non-blocking
			non_block_fd( pipefd[ 1 ] );
		}
		else
		{
			pipe_text = NULL;
		}
		argc -= 2;
		li += 2;
	}

	// prepares the arguments
	argv = s_calloc( argc + 2, sizeof( char * ) );
	argv[ 0 ] = binary;
	for( i = 1; i <= argc; i++ )
		{ argv[i] = luaL_checkstring( L, i + li ); }
	argv[ i ] = NULL;

	// the fork!
	pid = fork( );

	if( pid == 0 )
	{
		// replaces stdin for pipes
		if( pipe_text )
			{ dup2( pipefd[ 0 ], STDIN_FILENO ); }

		// if lsyncd runs as a daemon and has a logfile it will redirect
		// stdout/stderr of child processes to the logfile.
		if( is_daemon && settings.log_file )
		{
			if( !freopen( settings.log_file, "a", stdout ) )
			{
				printlogf(
					L, "Error",
					"cannot redirect stdout to '%s'.",
					settings.log_file
				);
			}

			if( !freopen( settings.log_file, "a", stderr ) )
			{
				printlogf(
					L, "Error",
					"cannot redirect stderr to '%s'.",
					settings.log_file
				);
			}
		}

		execv( binary, ( char ** ) argv );

		// in a sane world execv does not return!
		printlogf(
			L, "Error",
			"Failed executing [ %s ]!",
			binary
		);

		exit( -1 );
	}

	if( pipe_text )
	{
		int len;

		// first closes read-end of pipe, this is for child process only
		close( pipefd[ 0 ] );

		// starts filling the pipe
		len = write( pipefd[ 1 ], pipe_text, pipe_len );

		if( len < 0 )
		{
			logstring( "Normal", "immediatly broken pipe." );
			close( pipefd[ 1 ] );
		}
		else if( len == pipe_len )
		{
			// usual and best case, the pipe accepted all input -> close
			close( pipefd[ 1 ] );
			logstring( "Exec", "one-sweeped pipe" );
		}
		else
		{
			struct pipemsg *pm;
			logstring( "Exec", "adding pipe observance" );
			pm = s_calloc( 1, sizeof( struct pipemsg ) );
			pm->text = s_calloc( pipe_len + 1, sizeof( char ) );
			memcpy( pm->text, pipe_text, pipe_len + 1 );
			pm->tlen = pipe_len;
			pm->pos  = len;

			observe_fd(
				pipefd[ 1 ],
				NULL,
				pipe_writey,
				pipe_tidy,
				pm
			);
		}
	}

	free( argv );
	lua_pushnumber( L, pid );

	return 1;
}
Example #22
0
static int aux_getfenv (lua_State *L) {
  lua_getfenv(L, -1);
  lua_pushliteral(L, "__fenv");
  lua_rawget(L, -2);
  return !lua_isnil(L, -1);
}
Example #23
0
const char *luaex_cmd_Reslist(cmd_parms *cmd,
                              void *dcfg,
                              const char *resource, const char *script)
{
  struct dir_config *conf = dcfg;
  const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
  module* lua_module = ml_find_module(cmd->server, "lua_module");

  if (err != NULL)
    return err;

  if (conf->resource == NULL)
  {
    conf->resource = apr_hash_make(cmd->pool);
  }
  if (conf->L == NULL)
  {
    conf->L = luaL_newstate();
#ifdef AP_ENABLE_LUAJIT
    luaopen_jit(conf->L);
#endif
    luaL_openlibs(conf->L);
  }


  if (apr_hash_get(conf->resource, resource, strlen(resource)) == NULL)
  {
    lua_State *L = conf->L;
    int err = luaL_loadfile(L, script);
    if (err == LUA_ERRFILE)
      return apr_psprintf(cmd->pool, "cannot open/read: %s. ", script);
    if (err == LUA_ERRSYNTAX)
      return apr_psprintf(cmd->pool, "syntax error during pre-compilation for: %s. ", script);
    if (err == LUA_ERRMEM)
      return apr_psprintf(cmd->pool, "memory allocation error for load: %s. ", script);
    if (err)
      return apr_psprintf(cmd->pool, "unknown error)(%d) for load: %s. ", err, script);

    err = lua_pcall(L, 0, LUA_MULTRET, 0);
    if (err == LUA_ERRRUN)
      return apr_psprintf(cmd->pool, "a runtime error. %s", lua_tostring(L, -1));
    if (err == LUA_ERRMEM)
      return apr_psprintf(cmd->pool, "memory allocation error. %s", lua_tostring(L, -1));
    if (err == LUA_ERRERR)
      return apr_psprintf(cmd->pool, "error while running the error handler function. %s", lua_tostring(L, -1));
    if (err)
      return apr_psprintf(cmd->pool, "unknown error(%d:%s) for load: %s. ", err, lua_tostring(L, -1), script);

    {
      int min, smax, hmax, ttl;
      apr_reslist_t* reslist;
      reslist_cb_t* cb = apr_palloc(cmd->pool, sizeof(reslist_cb_t));

      luaL_getmetatable(L, resource);
      if (lua_isnil(L, -1))
        return apr_psprintf(cmd->pool, "%s not support %s object(metatable)", script, resource);
      cb->name = resource;
      lua_pop(L, 1);

      if (!lua_istable(L, -1))
        return apr_psprintf(cmd->pool, "%s not return a table which makes a reslist for %s", script, resource);

      cb->L = conf->L;
      lua_getfield(L, -1, "constructor");
      if (!lua_isfunction(L, -1))
        return apr_psprintf(cmd->pool, "%s not have a table field(constructor) function", script);
      cb->constructor_ref = luaL_ref(L, LUA_REGISTRYINDEX);

      lua_getfield(L, -1, "destructor");
      if (!lua_isfunction(L, -1))
        return apr_psprintf(cmd->pool, "%s not have a table field(destructor) function", script);
      cb->destructor_ref = luaL_ref(L, LUA_REGISTRYINDEX);

      lua_getfield(L, -1, "min");
      min = luaL_optint(L, -1, 0);
      lua_pop(L, 1);

      lua_getfield(L, -1, "smax");
      smax = luaL_optint(L, -1, 16);
      lua_pop(L, 1);

      lua_getfield(L, -1, "hmax");
      hmax = luaL_optint(L, -1, 16);
      lua_pop(L, 1);

      lua_getfield(L, -1, "ttl");
      ttl = luaL_optint(L, -1, 0);
      lua_pop(L, 1);

      if (apr_reslist_create(&reslist, min, smax, hmax, ttl, ml_apr_reslist_constructor, ml_apr_reslist_destructor, cb, cmd->pool)
          == APR_SUCCESS)
      {
        apr_hash_set(conf->resource, resource, strlen(resource), reslist);
      }
      else
        return "apr_reslist_create failed";
    }
  }

  if (conf->resource == NULL)
    return "Out of memory";

  return NULL;
}
// add_particlespawner({amount=, time=,
//				minpos=, maxpos=,
//				minvel=, maxvel=,
//				minacc=, maxacc=,
//				minexptime=, maxexptime=,
//				minsize=, maxsize=,
//				collisiondetection=,
//				collision_removal=,
//				vertical=,
//				texture=,
//				player=})
// minpos/maxpos/minvel/maxvel/minacc/maxacc = {x=num, y=num, z=num}
// minexptime/maxexptime = num (seconds)
// minsize/maxsize = num
// collisiondetection = bool
// collision_removal = bool
// vertical = bool
// texture = e.g."default_wood.png"
// animation = TileAnimation definition
// glow = num
int ModApiParticles::l_add_particlespawner(lua_State *L)
{
	MAP_LOCK_REQUIRED;

	// Get parameters
	u16 amount = 1;
	v3f minpos, maxpos, minvel, maxvel, minacc, maxacc;
	    minpos= maxpos= minvel= maxvel= minacc= maxacc= v3f(0, 0, 0);
	float time, minexptime, maxexptime, minsize, maxsize;
	      time= minexptime= maxexptime= minsize= maxsize= 1;
	bool collisiondetection, vertical, collision_removal;
	     collisiondetection = vertical = collision_removal = false;
	struct TileAnimationParams animation;
	animation.type = TAT_NONE;
	ServerActiveObject *attached = NULL;
	std::string texture = "";
	std::string playername = "";
	u8 glow = 0;

	if (lua_gettop(L) > 1) //deprecated
	{
		log_deprecated(L,"Deprecated add_particlespawner call with individual parameters instead of definition");
		amount = luaL_checknumber(L, 1);
		time = luaL_checknumber(L, 2);
		minpos = check_v3f(L, 3);
		maxpos = check_v3f(L, 4);
		minvel = check_v3f(L, 5);
		maxvel = check_v3f(L, 6);
		minacc = check_v3f(L, 7);
		maxacc = check_v3f(L, 8);
		minexptime = luaL_checknumber(L, 9);
		maxexptime = luaL_checknumber(L, 10);
		minsize = luaL_checknumber(L, 11);
		maxsize = luaL_checknumber(L, 12);
		collisiondetection = lua_toboolean(L, 13);
		texture = luaL_checkstring(L, 14);
		if (lua_gettop(L) == 15) // only spawn for a single player
			playername = luaL_checkstring(L, 15);
	}
	else if (lua_istable(L, 1))
	{
		amount = getintfield_default(L, 1, "amount", amount);
		time = getfloatfield_default(L, 1, "time", time);

		lua_getfield(L, 1, "minpos");
		minpos = lua_istable(L, -1) ? check_v3f(L, -1) : minpos;
		lua_pop(L, 1);

		lua_getfield(L, 1, "maxpos");
		maxpos = lua_istable(L, -1) ? check_v3f(L, -1) : maxpos;
		lua_pop(L, 1);

		lua_getfield(L, 1, "minvel");
		minvel = lua_istable(L, -1) ? check_v3f(L, -1) : minvel;
		lua_pop(L, 1);

		lua_getfield(L, 1, "maxvel");
		maxvel = lua_istable(L, -1) ? check_v3f(L, -1) : maxvel;
		lua_pop(L, 1);

		lua_getfield(L, 1, "minacc");
		minacc = lua_istable(L, -1) ? check_v3f(L, -1) : minacc;
		lua_pop(L, 1);

		lua_getfield(L, 1, "maxacc");
		maxacc = lua_istable(L, -1) ? check_v3f(L, -1) : maxacc;
		lua_pop(L, 1);

		minexptime = getfloatfield_default(L, 1, "minexptime", minexptime);
		maxexptime = getfloatfield_default(L, 1, "maxexptime", maxexptime);
		minsize = getfloatfield_default(L, 1, "minsize", minsize);
		maxsize = getfloatfield_default(L, 1, "maxsize", maxsize);
		collisiondetection = getboolfield_default(L, 1,
			"collisiondetection", collisiondetection);
		collision_removal = getboolfield_default(L, 1,
			"collision_removal", collision_removal);

		lua_getfield(L, 1, "animation");
		animation = read_animation_definition(L, -1);
		lua_pop(L, 1);

		lua_getfield(L, 1, "attached");
		if (!lua_isnil(L, -1)) {
			ObjectRef *ref = ObjectRef::checkobject(L, -1);
			lua_pop(L, 1);
			attached = ObjectRef::getobject(ref);
		}

		vertical = getboolfield_default(L, 1, "vertical", vertical);
		texture = getstringfield_default(L, 1, "texture", "");
		playername = getstringfield_default(L, 1, "playername", "");
		glow = getintfield_default(L, 1, "glow", 0);
	}

	u32 id = getServer(L)->addParticleSpawner(amount, time,
			minpos, maxpos,
			minvel, maxvel,
			minacc, maxacc,
			minexptime, maxexptime,
			minsize, maxsize,
			collisiondetection,
			collision_removal,
			attached,
			vertical,
			texture, playername,
			animation, glow);
	lua_pushnumber(L, id);

	return 1;
}
// implements IVisCallbackHandler_cl
void vHavokBehaviorModule::OnHandleCallback(IVisCallbackDataObject_cl *pData)
{
	// Setup
	// Register vision callbacks
	if( pData->m_pSender == &Vision::Callbacks.OnUpdateSceneBegin )
	{
		checkEditorModeChanged();
		stepModule();
	}
	else if( pData->m_pSender == &Vision::Callbacks.OnAfterSceneLoaded )
	{
		// Set physics module
		vHavokPhysicsModule* physicsModule = vHavokPhysicsModule::GetInstance();
		if( physicsModule != HK_NULL )
		{
			hkpWorld* physicsWorld = physicsModule->GetPhysicsWorld();

			// Set world gravity
			physicsWorld->markForRead();
			{
				hkVector4 up;
				up.setNeg3( physicsWorld->getGravity() );
				up.normalize3();

				m_behaviorWorld->setUp( up );
			}
			physicsWorld->unmarkForRead();
		}
		else
		{
			hkVector4 up; vHavokConversionUtils::VisVecToPhysVec_noscale( m_visionCharacters[0]->getEntityOwner()->GetObjDir_Up(), up );
			m_behaviorWorld->setUp( up );
		}

	}
	else if( pData->m_pSender == &Vision::Callbacks.OnAfterSceneUnloaded )
	{
/*#if defined(HAVOK_SDK_VERSION_MAJOR) && (HAVOK_SDK_VERSION_MAJOR >= 2012)
		// destroy all unreferenced navmesh instances
		m_projectAssetManager->clearAssets();

		hkbOnHeapAssetLoader* assetLoader = static_cast<hkbOnHeapAssetLoader*>( m_assetLoader );
		assetLoader->unloadAllAssets();

		HK_ASSERT(0x21e79cc1, m_visionCharacters.getSize() == 0 );

		// unload all unused resources
		vHavokBehaviorResourceManager::GetInstance()->PurgeUnusedResources();

		HK_ASSERT(0xc5b3c4e, vHavokBehaviorResourceManager::GetInstance()->GetResourceCount() == 0 );
#endif*/
	}
	else if( pData->m_pSender == &vHavokPhysicsModule::OnBeforeInitializePhysics )
	{
		vHavokPhysicsModuleCallbackData *pHavokData = (vHavokPhysicsModuleCallbackData*)pData;
		VISION_HAVOK_SYNC_STATICS();
		VISION_HAVOK_SYNC_PER_THREAD_STATICS( pHavokData->GetHavokModule() );

		// Register Behavior classes
		{
			hkDefaultClassNameRegistry& dcnReg	= hkDefaultClassNameRegistry::getInstance();
			hkTypeInfoRegistry&			tyReg	= hkTypeInfoRegistry::getInstance();
			hkVtableClassRegistry&		vtcReg	= hkVtableClassRegistry::getInstance();

#ifndef VBASE_LIB  // DLL, so have a full set 
			dcnReg.registerList(hkBuiltinTypeRegistry::StaticLinkedClasses);
			tyReg.registerList(hkBuiltinTypeRegistry::StaticLinkedTypeInfos);
			vtcReg.registerList(hkBuiltinTypeRegistry::StaticLinkedTypeInfos, hkBuiltinTypeRegistry::StaticLinkedClasses);
#else // Static lib, just need to add Behavior ones and reg the Behavior patches which would not have been done yet
			dcnReg.registerList(hkBuiltinBehaviorTypeRegistry::StaticLinkedClasses);
			tyReg.registerList(hkBuiltinBehaviorTypeRegistry::StaticLinkedTypeInfos);
			vtcReg.registerList(hkBuiltinBehaviorTypeRegistry::StaticLinkedTypeInfos, hkBuiltinBehaviorTypeRegistry::StaticLinkedClasses);
#endif
		}

		registerAnimationBehaviorPatches();
		hkVersionPatchManager::getInstance().recomputePatchDependencies();

		OneTimeInit();
	}
	else if( pData->m_pSender == &vHavokPhysicsModule::OnAfterInitializePhysics )
	{
		vHavokPhysicsModuleCallbackData *pHavokData = (vHavokPhysicsModuleCallbackData*)pData;
		vHavokPhysicsModule* physicsModule = pHavokData->GetHavokModule();
		InitWorld( physicsModule );
	}
	else if( pData->m_pSender == &vHavokPhysicsModule::OnBeforeDeInitializePhysics )
	{
		DeInitWorld();
	}
	else if( pData->m_pSender == &vHavokPhysicsModule::OnAfterDeInitializePhysics )
	{
		// Unload everything, the scene gets deleted!
		OneTimeDeInit();
	}
	else if( pData->m_pSender == &vHavokPhysicsModule::OnUnsyncHavokStatics )
	{
		vHavokPhysicsModuleCallbackData *pHavokData = (vHavokPhysicsModuleCallbackData*)pData;
		VISION_HAVOK_UNSYNC_STATICS();
		VISION_HAVOK_UNSYNC_PER_THREAD_STATICS( pHavokData->GetHavokModule() );
	}
	else if( pData->m_pSender == &vHavokPhysicsModule::OnBeforeWorldCreated )
	{
		vHavokBeforeWorldCreateDataObject_cl *pEventData = (vHavokBeforeWorldCreateDataObject_cl *)pData;
		hkJobQueue* jobQueue = pEventData->GetHavokModule()->GetJobQueue();
		if( jobQueue != HK_NULL )
		{
			hkbBehaviorJobQueueUtils::registerWithJobQueue( jobQueue );
		}
	}
	else if( pData->m_pSender == &vHavokVisualDebugger::OnCreatingContexts )
	{
		hkbBehaviorContext::registerAllBehaviorViewers();

		vHavokVisualDebuggerCallbackData_cl *pEventData = (vHavokVisualDebuggerCallbackData_cl *)pData;
		pEventData->m_contexts->pushBack( m_behaviorContext );
	}
	else if( pData->m_pSender == &vHavokVisualDebugger::OnAddingDefaultViewers )
	{
		vHavokVisualDebuggerCallbackData_cl *pEventData = (vHavokVisualDebuggerCallbackData_cl *)pData;
		if( pEventData->m_pVisualDebugger != HK_NULL )
		{
			hkbBehaviorContext::addDefaultViewers( pEventData->m_pVisualDebugger );
		}
	}
#ifdef VLUA_USE_SWIG_BINDING
	else if( pData->m_pSender == &IVScriptManager::OnRegisterScriptFunctions )
	{
		EnsureHavokBehaviorScriptRegistration();
	}
	else if (pData->m_pSender==&IVScriptManager::OnScriptProxyCreation)
	{
		VScriptCreateStackProxyObject * pScriptData = (VScriptCreateStackProxyObject *)pData;

		// process data only if no other callback did that
		if(!pScriptData->m_bProcessed)
		{
			int iRetParams = 0;

			// call appropriate LUA cast function
			if(pScriptData->m_pInstance->IsOfType(V_RUNTIME_CLASS(vHavokBehaviorComponent)))
			{
				iRetParams = LUA_CallStaticFunction( pScriptData->m_pLuaState, "Behavior", "vHavokBehaviorComponent", "Cast", "E>E",  pScriptData->m_pInstance );
			}

			// could we handle the object?
			if(iRetParams>0)
			{
				// the cast failed if the result is a nil value
				if(lua_isnil(pScriptData->m_pLuaState, -1))
					lua_pop(pScriptData->m_pLuaState, iRetParams); //in case of a nil value we drop the params from the lua stack
				else
					pScriptData->m_bProcessed = true; //avoid further processing
			}
		}
	}
#endif

}
static
int ngx_http_lua_shlist_push(lua_State *L)
{
    ngx_http_lua_shlist_node_t  *node;
    ngx_shm_zone_t              *zone;
    ngx_str_t                    value;
    ngx_http_lua_shlist_ctx_t   *ctx;
    double                       num;
    int                          n;
    int                          value_type;
   
    n = lua_gettop(L);

    if (n != 2) {
        return luaL_error(L, "expecting 2 arguments, but seen %d", n);
    }

    if (lua_type(L, 1) != LUA_TTABLE) {
        return luaL_error(L, "bad \"temp table zone\" argument");
    }

    
    zone = ngx_http_lua_shlist_get_zone(L, 1);
    if (zone == NULL) {
        return luaL_error(L, "bad \"zone\" argument");
    }

    ctx = zone->data;

    if (lua_isnil(L, 2)) {    // 不允许插入空值 
        lua_pushnil(L);
        lua_pushliteral(L, "nil value");
    }

    value_type = lua_type(L, 2);  // 第二个参数就是要入栈的
    // dd("value_type: %n", &value_type);

    switch (value_type) {
        case LUA_TSTRING:
            value.data = (u_char *) lua_tolstring(L, 2, &value.len);
            break;
        case LUA_TNUMBER:
            value.len = sizeof(double);
            num = lua_tonumber(L, 2);
            value.data = (u_char *) &num;
            break;
        case LUA_TNIL:
            lua_pushnil(L);
            lua_pushliteral(L, "attempt to add nil to list");
            return 2;
        default:
            lua_pushnil(L);
            lua_pushliteral(L, "bad value type");
            return 2;
    }

    ngx_shmtx_lock(&ctx->shpool->mutex);

    n = offsetof(ngx_http_lua_shlist_node_t, data)  // 计算足够大小的空间
        + value.len;

    node = ngx_slab_alloc_locked(ctx->shpool, n);   // 申请

    if (node == NULL) {
        ngx_shmtx_unlock(&ctx->shpool->mutex);

        lua_pushboolean(L, 0);
        lua_pushliteral(L, "no memory");
        return 2;
    }

    node->value_len  = (uint32_t) value.len;
    node->value_type = (uint8_t) value_type;

    ngx_memcpy(node->data, value.data, value.len);

    ngx_queue_insert_tail(&ctx->sh->queue, &node->queue);

    ngx_shmtx_unlock(&ctx->shpool->mutex);

    lua_pushboolean(L, 1); // push success flag
    lua_pushnil(L);  // no error
    return 2;
}
Example #27
0
/// Wrapper around lua_isnil.
///
/// \param index The second parameter to lua_isnil.
///
/// \return The return value of lua_isnil.
bool
lutok::state::is_nil(const int index)
{
    return lua_isnil(_pimpl->lua_state, index);
}
//box[], particles[], shapes[]
static int luaScene_load(lua_State* L){
    SimConfig config;

    for(lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)){
        long long int i = lua_tointeger(L, -2) - 1;
        if(i < 0 || i >= 9){
            fprintf(stderr, "Invalid index for box table encountered while loading scene.\n");
            return 0;
        }
        config.box[i % 3][i / 3] = lua_tonumber(L, -1);
    }

    config.n_particles = lua_rawlen(L, 2);
    config.particles = new Particle[config.n_particles];

    size_t pid = 0;
    for(lua_pushnil(L); lua_next(L, 2);){
        config.particles[pid++] = maan::get_LuaValue<Particle>(L);
    }

    config.n_shapes = lua_rawlen(L, 3);
    config.shapes = new Shape[config.n_shapes];

    //TODO: Add a is_class(lua_State* L, int idx) function to maan.
    size_t sid = 0;
    for(lua_pushnil(L); lua_next(L, 3);){
        if(!lua_isuserdata(L, -1)){
            fprintf(stderr, "Unknown item type encountered in shapes table while loading scene. 'Shape' expected, got '%s'.\n", luaL_typename(L, -1));
            delete[] config.particles;
            delete[] config.shapes;
            return 0;
        }
        lua_getmetatable(L, -1);
        lua_pushstring(L, "__class_id");
        lua_rawget(L, -2);
        if(lua_isnil(L, -1)){
            fprintf(stderr, "Unknown userdata type encountered in shapes table while loading scene.\n");
            delete[] config.particles;
            delete[] config.shapes;
            return 0;
        }

        void* class_id = lua_touserdata(L, -1);
        lua_pop(L, 2);
        auto shape = Shape();
        if(maan::detail::ClassInfo<Sphere>::get_metatable_key() == class_id){
            shape.type = Shape::SPHERE;
            lua_pop(L, 1);
        }
        else if(maan::detail::ClassInfo<Mesh>::get_metatable_key() == class_id){
            shape.type = Shape::MESH;
            auto mesh = maan::get_LuaValue<Mesh>(L);
            shape.mesh.n_vertices = mesh.vertices_.size();
            shape.mesh.vertices = new Vertex[shape.mesh.n_vertices];
            int i = 0;
            for(auto vertex: mesh.vertices_){
                shape.mesh.vertices[i++] = vertex;
            }
        }
        else{
            lua_getmetatable(L, -1);
            lua_pushstring(L, "__name");
            lua_rawget(L, -2);
            fprintf(stderr, "Unknown class type encountered in shapes table while loading scene. 'Shape' expected, got '%s'.\n", lua_tostring(L, -1));
            lua_pop(L, 2);
            delete[] config.particles;
            delete[] config.shapes;
            return 0;
        }
        config.shapes[sid++] = shape;
    }

    auto scene = reinterpret_cast<Scene*>(lua_touserdata(L, lua_upvalueindex(1)));

    scene->load_scene(config);

    delete[] config.particles;
    delete[] config.shapes;

    return 0;
}
Example #29
0
int NativeDelegate::__op_minusassignment(lua_State *L)
{
    NativeDelegate *delegate = (NativeDelegate *)lualoom_getnativepointer(L, 1,
                                                                          "system.NativeDelegate");

    if (!delegate)
    {
        LSError("Unable to get native delegate on += operator");
    }

    if (!delegate->_callbackCount)
    {
        return 0;
    }

    delegate->setVM(L);

    delegate->getCallbacks(L);

    int tidx = lua_gettop(L);

    if (!lua_istable(L, tidx))
    {
        LSError("Bad native delegates table");
    }

    if (lua_isfunction(L, 2) || lua_iscfunction(L, 2))
    {
        int idx = -1;
        for (int i = 0; i < delegate->_callbackCount; i++)
        {
            lua_rawgeti(L, tidx, i);
            if (lua_equal(L, 2, -1))
            {
                idx = i;
                lua_pop(L, 1);
                break;
            }
            lua_pop(L, 1);
        }


        // this function was never added in the first place
        if (idx == -1)
        {
            return 0;
        }

        // shift the other delegates down
        lua_pushnumber(L, (double)idx);
        lua_pushnil(L);
        lua_settable(L, tidx);

        int ntable = 0;
        if (delegate->_callbackCount > 1)
        {
            // temp table
            lua_newtable(L);
            ntable = lua_gettop(L);

            int c = 0;
            for (int nidx = 0; nidx < delegate->_callbackCount; nidx++)
            {
                lua_pushnumber(L, (double)nidx);
                lua_gettable(L, tidx);
                if (lua_isnil(L, -1))
                {
                    lua_pop(L, 1);
                    continue;
                }

                lua_pushnumber(L, (double)c);
                lua_pushvalue(L, -2);
                lua_settable(L, ntable);
                // pop lua_function
                lua_pop(L, 1);
                c++;
            }
        }

        // clear it
        delegate->_callbackCount--;

        // and copy from new temp table
        for (int nidx = 0; nidx < delegate->_callbackCount; nidx++)
        {
            lua_pushnumber(L, (double)nidx);
            lua_pushnumber(L, (double)nidx);
            lua_gettable(L, ntable);
            lua_settable(L, tidx);
        }
    }
    else
    {
        LSError("Unknown type on NativeDelegate -= operator");
    }

    return 0;
}
Example #30
0
/* Top-level delegating persist function
 */
static void persist(PersistInfo *pi)
{
	/* Grab the object's type. */
	int type = lua_type(pi->L, -1);
	int simple = type == LUA_TNIL 
		|| type == LUA_TBOOLEAN 
		|| type == LUA_TNUMBER 
		|| type == LUA_TLIGHTUSERDATA;
  
	/* Increment the number of objects persisted. */
	++(pi->counter);
  
	/* If the type isn't simple, check to see if
	   one is already in the reftable. */
	if(!simple) {

		/* perms reftbl ... obj */
		lua_checkstack(pi->L, 2);
		/* If the object has already been written, write a reference to it */
		lua_pushvalue(pi->L, -1);
		/* perms reftbl ... obj obj */
		lua_rawget(pi->L, 2);
		/* perms reftbl ... obj ref? */
		if(!lua_isnil(pi->L, -1)) {
			/* perms reftbl ... obj ref */
			int zero = 0;
			int ref = (intptr_t)lua_touserdata(pi->L, -1);
			pi->writer(pi->L, &zero, sizeof(int), pi->ud);
			pi->writer(pi->L, &ref, sizeof(int), pi->ud);
			lua_pop(pi->L, 1);
			/* perms reftbl ... obj ref */
#ifdef PLUTO_DEBUG
			printindent(pi->level);
			printf("0 %d\n", ref);
#endif
			return;
		}
		/* perms reftbl ... obj nil */
		lua_pop(pi->L, 1);

	}

					/* perms reftbl ... obj */
	/* If the object is nil, write the pseudoreference 0 */
	if(lua_isnil(pi->L, -1)) {
		int zero = 0;
		/* firsttime */
		pi->writer(pi->L, &zero, sizeof(int), pi->ud);
		/* ref */
		pi->writer(pi->L, &zero, sizeof(int), pi->ud);
#ifdef PLUTO_DEBUG
		printindent(pi->level);
		printf("0 0\n");
#endif
		return;
	}
	{
		/* indicate that it's the first time */
		int one = 1;
		pi->writer(pi->L, &one, sizeof(int), pi->ud);
	}

	/* put the value in the reftable if necessary.
	   Simple types don't need to be put in the reftable. */
	if(!simple) {
		lua_pushvalue(pi->L, -1);
		/* perms reftbl ... obj obj */
		lua_pushlightuserdata(pi->L, (void*)((intptr_t) pi->counter));
		/* perms reftbl ... obj obj ref */
		lua_rawset(pi->L, 2);
		/* perms reftbl ... obj */
	}

	pi->writer(pi->L, &pi->counter, sizeof(int), pi->ud);


	/* At this point, we'll give the permanents table a chance to play. */
	{
		lua_pushvalue(pi->L, -1);
					/* perms reftbl ... obj obj */
		lua_gettable(pi->L, 1);
					/* perms reftbl ... obj permkey? */
		if(!lua_isnil(pi->L, -1)) {
					/* perms reftbl ... obj permkey */
			int type = PLUTO_TPERMANENT;
#ifdef PLUTO_DEBUG
			printindent(pi->level);
			printf("1 %d PERM\n", pi->counter);
			pi->level++;
#endif
			pi->writer(pi->L, &type, sizeof(int), pi->ud);
			persist(pi);
			lua_pop(pi->L, 1);
					/* perms reftbl ... obj */
#ifdef PLUTO_DEBUG
			pi->level--;
#endif
			return;
		} else {
					/* perms reftbl ... obj nil */
			lua_pop(pi->L, 1);
					/* perms reftbl ... obj */
		}
					/* perms reftbl ... obj */
	}
	{
		int type = lua_type(pi->L, -1);
		pi->writer(pi->L, &type, sizeof(int), pi->ud);

#ifdef PLUTO_DEBUG
		printindent(pi->level);
		printf("1 %d %d\n", pi->counter, type);
		pi->level++;
#endif
	}

	switch(lua_type(pi->L, -1)) {
		case LUA_TBOOLEAN:
			persistboolean(pi);
			break;
		case LUA_TLIGHTUSERDATA:
			persistlightuserdata(pi);
			break;
		case LUA_TNUMBER:
			persistnumber(pi);
			break;
		case LUA_TSTRING:
			persiststring(pi);
			break;
		case LUA_TTABLE:
			persisttable(pi);
			break;
		case LUA_TFUNCTION:
			persistfunction(pi);
			break;
		case LUA_TTHREAD:
			persistthread(pi);
			break;
		case LUA_TPROTO:
			persistproto(pi);
			break;
		case LUA_TUPVAL:
			persistupval(pi);
			break;
		case LUA_TUSERDATA:
			persistuserdata(pi);
			break;
		default:
			lua_assert(0);
	}
#ifdef PLUTO_DEBUG
	pi->level--;
#endif
}